aboutsummaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
authorJack Ren <jack.ren@intel.com>2012-01-17 16:27:42 +0800
committerJack Ren <jack.ren@intel.com>2012-03-12 23:14:56 +0800
commitd8bc6e7119450f263afcf89c8b581f6aaa23d186 (patch)
tree00a129ca73e415545e7a629ceb1ec4e7bbe525ef /libc
parenta58c88c235bfeeb17ac495991e66f7b906935852 (diff)
downloadandroid_bionic-d8bc6e7119450f263afcf89c8b581f6aaa23d186.tar.gz
android_bionic-d8bc6e7119450f263afcf89c8b581f6aaa23d186.tar.bz2
android_bionic-d8bc6e7119450f263afcf89c8b581f6aaa23d186.zip
bionic: Fix wrong kernel_id in pthread descriptor after fork()
After forking, the kernel_id field in the phtread_internal_t returned by pthread_self() is incorrect --- it's the tid from the parent, not the new tid of the child. The root cause is that: currently the kernel_id is set by _init_thread(), which is called in 2 cases: (1) called by __libc_init_common(). That happens when the execv( ) is called after fork( ). But when the zygote tries to fork the android application, the child application doesn't call execv( ), instread, it tries to call the Java main method directly. (2) called by pthread_create(). That happens when a new thread is created. For the lead thread which is the thread created by fork(), it should call execv() but it doesn't, as described in (1) above. So its kernel_id will inherit the parent's kernel_id. Fixed it in this patch. Change-Id: I63513e82af40ec5fe51fbb69456b1843e4bc0fc7 Signed-off-by: Chenyang Du <chenyang.du@intel.com> Signed-off-by: Jack Ren <jack.ren@intel.com> Signed-off-by: Bruce Beare <bruce.j.beare@intel.com>
Diffstat (limited to 'libc')
-rw-r--r--libc/bionic/fork.c4
-rw-r--r--libc/bionic/pthread.c11
-rw-r--r--libc/private/bionic_pthread.h1
3 files changed, 16 insertions, 0 deletions
diff --git a/libc/bionic/fork.c b/libc/bionic/fork.c
index 0eedb0119..2d5a10a8d 100644
--- a/libc/bionic/fork.c
+++ b/libc/bionic/fork.c
@@ -27,6 +27,7 @@
*/
#include <unistd.h>
#include "pthread_internal.h"
+#include "bionic_pthread.h"
#include "cpuacct.h"
extern int __fork(void);
@@ -48,6 +49,9 @@ int fork(void)
__timer_table_start_stop(0);
__bionic_atfork_run_parent();
} else {
+ /* Adjusting the kernel id after a fork */
+ (void)__pthread_settid(pthread_self(), gettid());
+
/*
* Newly created process must update cpu accounting.
* Call cpuacct_add passing in our uid, which will take
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 3435d219c..885adccb5 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -2011,3 +2011,14 @@ pid_t __pthread_gettid(pthread_t thid)
pthread_internal_t* thread = (pthread_internal_t*)thid;
return thread->kernel_id;
}
+
+int __pthread_settid(pthread_t thid, pid_t tid)
+{
+ if (thid == 0)
+ return EINVAL;
+
+ pthread_internal_t* thread = (pthread_internal_t*)thid;
+ thread->kernel_id = tid;
+
+ return 0;
+}
diff --git a/libc/private/bionic_pthread.h b/libc/private/bionic_pthread.h
index 07bcbd4b0..28d6ad83e 100644
--- a/libc/private/bionic_pthread.h
+++ b/libc/private/bionic_pthread.h
@@ -35,6 +35,7 @@ __BEGIN_DECLS
/* Internal, not an NDK API */
extern pid_t __pthread_gettid(pthread_t thid);
+extern int __pthread_settid(pthread_t thid, pid_t tid);
__END_DECLS