Handle pthread-related changes (mutex/atfork)
First commit: Revert "Revert "am be741d47: am 2f460fbe: am 73b5cad9: Merge "bionic: Fix wrong kernel_id in pthread descriptor after fork()""" This reverts commit 06823da2f0c8b4a4ce4c45113032f03df85c94b8. Second commit: bionic: fix atfork hanlder_mutex deadlock This cherry-picks commit 34e89c232dd5645fe3b5f9b40856d8e3e4cae57a After applying the kernel_id fix, the system refused to boot up and we got following crash log: I/DEBUG ( 113): pid: 618, tid: 618 >>> org.simalliance.openmobileapi.service:remote <<< I/DEBUG ( 113): signal 16 (SIGSTKFLT), code -6 (?), fault addr -------- I/DEBUG ( 113): eax fffffe00 ebx b77de994 ecx 00000080 edx 00724002 I/DEBUG ( 113): esi 00000000 edi 00004000 I/DEBUG ( 113): xcs 00000073 xds 0000007b xes 0000007b xfs 00000000 xss 0000007b I/DEBUG ( 113): eip b7761351 ebp bfdf3de8 esp bfdf3dc4 flags 00000202 I/DEBUG ( 113): #00 eip: 00015351 /system/lib/libc.so I/DEBUG ( 113): #01 eip: 0000d13c /system/lib/libc.so (pthread_mutex_lock) I/DEBUG ( 113): #02 eip: 00077b48 /system/lib/libc.so (__bionic_atfork_run_prepare) I/DEBUG ( 113): #03 eip: 00052cdb /system/lib/libc.so (fork) I/DEBUG ( 113): #04 eip: 0009ae91 /system/lib/libdvm.so (_Z18dvmOptimizeDexFileillPKcjjb) I/DEBUG ( 113): #05 eip: 000819d6 /system/lib/libdvm.so (_Z14dvmJarFileOpenPKcS0_PP7JarFileb) I/DEBUG ( 113): #06 eip: 000b175e /system/lib/libdvm.so (_ZL40Dalvik_dalvik_system_DexFile_openDexFilePKjP6JValue) I/DEBUG ( 113): #07 eip: 0011fb94 /system/lib/libdvm.so Root cause: The atfork uses the mutex handler_mutex to protect the atfork_head. The parent will call __bionic_atfork_run_prepare() to lock the handler_mutex, and need both the parent and child to unlock their own copy of handler_mutex after fork. At that time, the owner of hanlder_mutex is set as the parent. If we apply the kernel_id fix, then the child's kernel_id will be set as child's tid. The handler_mutex is a recursive lock, and pthread_mutex_unlock(&hander_mutex) will fail because the mutex owner is the parent, while the current tid (__get_thread()->kernel_id) is child, not matched with the mutex owner. At that time, the handler_mutex is left in lock state.If the child wants to fork other process after than, then it will try to lock handler_mutex, and then be deadlocked. Fix: Since the child has its own copy of vm space from the the parent, the child space's handler_mutex should be reset to the initialized state. Change-Id: I3907dd9a153418fb78862f2aa6d0302c375d9e27 Signed-off-by: Jack Ren <jack.ren@intel.com> Signed-off-by: Chenyang Du <chenyang.du@intel.com> Signed-off-by: Bruce Beare <bruce.j.beare@intel.com> Change-Id: Ic8072f366a877443a60fe215f3c00b3df5a259c8
This commit is contained in:
parent
126601dd3f
commit
faca92f2f1
@ -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
|
||||
|
@ -74,6 +74,7 @@ void __bionic_atfork_run_prepare()
|
||||
void __bionic_atfork_run_child()
|
||||
{
|
||||
struct atfork_t *cursor;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
/* Call pthread_atfork() child handlers */
|
||||
for (cursor = atfork_head.cqh_first;
|
||||
@ -84,7 +85,9 @@ void __bionic_atfork_run_child()
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&handler_mutex);
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&handler_mutex, &attr);
|
||||
}
|
||||
|
||||
void __bionic_atfork_run_parent()
|
||||
|
@ -2292,3 +2292,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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user