This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi! If a signal other than __pthread_sig_cancel is sent to a newly created thread before it INIT_THREAD_SELF in pthread_start_thread, it will have wrong thread_self (). The following patch should fix this (tested on i386 --without-tls --without-__thread non-FS, i686 --with-tls --without-__thread non-FS and i686 --with-tls --without-__thread FS). 2003-09-17 Jakub Jelinek <jakub@redhat.com> * pthread.c (manager_thread): Remove static, add attribute_hidden. (thread_self_stack): Rename to... (__pthread_self_stack): ... this. Remove static. (pthread_handle_sigcancel): Adjust caller. (pthread_handle_sigrestart): Do INIT_THREAD_SELF if signal is received before INIT_THREAD_SELF in pthread_start_thread. * sighandler.c (manager_thread): Define. (CHECK_THREAD_SELF): Define. (__pthread_sighandler, __pthread_sighandler_rt): Use it. * descr.h (manager_thread): Declare. * internals.h (__pthread_self_stack): New prototype. --- libc/linuxthreads/pthread.c.jj 2003-09-02 03:08:54.000000000 -0400 +++ libc/linuxthreads/pthread.c 2003-09-16 16:29:56.000000000 -0400 @@ -55,7 +55,7 @@ extern struct __res_state _res; #ifdef USE_TLS /* We need only a few variables. */ -static pthread_descr manager_thread; +pthread_descr manager_thread attribute_hidden; #else @@ -896,7 +896,7 @@ pthread_descr __pthread_find_self(void) #else -static pthread_descr thread_self_stack(void) +pthread_descr __pthread_self_stack(void) { char *sp = CURRENT_STACK_FRAME; pthread_handle h; @@ -1024,6 +1024,22 @@ static void pthread_atexit_retcode(void static void pthread_handle_sigrestart(int sig) { pthread_descr self = thread_self(); +#if defined THREAD_SELF && defined INIT_THREAD_SELF + if (self == manager_thread) + { + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + pthread_descr real_self = __pthread_self_stack(); + if (real_self != manager_thread) + { + /* Oops, thread_self() isn't working yet.. */ + self = real_self; + INIT_THREAD_SELF(self, self->p_nr); + } + } +#endif THREAD_SETMEM(self, p_signal, sig); if (THREAD_GETMEM(self, p_signal_jmp) != NULL) siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); @@ -1046,7 +1062,7 @@ static void pthread_handle_sigcancel(int initialized, so that the thread register might still point to the manager thread. Double check that this is really the manager thread. */ - pthread_descr real_self = thread_self_stack(); + pthread_descr real_self = __pthread_self_stack(); if (real_self == manager_thread) { __pthread_manager_sighandler(sig); --- libc/linuxthreads/internals.h.jj 2003-09-02 03:08:54.000000000 -0400 +++ libc/linuxthreads/internals.h 2003-09-16 16:29:00.000000000 -0400 @@ -363,6 +363,7 @@ extern int __pthread_condattr_init (pthr extern int __pthread_condattr_destroy (pthread_condattr_t *attr); extern pthread_t __pthread_self (void); extern pthread_descr __pthread_thread_self (void); +extern pthread_descr __pthread_self_stack (void) attribute_hidden; extern int __pthread_equal (pthread_t thread1, pthread_t thread2); extern void __pthread_exit (void *retval); extern int __pthread_getschedparam (pthread_t thread, int *policy, --- libc/linuxthreads/descr.h.jj 2003-07-23 03:56:17.000000000 -0400 +++ libc/linuxthreads/descr.h 2003-09-16 16:26:35.000000000 -0400 @@ -217,6 +217,7 @@ extern char *__pthread_manager_thread_to /* Descriptor of the manager thread */ extern struct _pthread_descr_struct __pthread_manager_thread; +extern pthread_descr manager_thread attribute_hidden; /* Indicate whether at least one thread has a user-defined stack (if 1), or all threads have stacks supplied by LinuxThreads (if 0). */ --- libc/linuxthreads/sighandler.c.jj 2002-05-03 03:36:37.000000000 -0400 +++ libc/linuxthreads/sighandler.c 2003-09-16 16:35:48.000000000 -0400 @@ -16,6 +16,31 @@ #include "internals.h" +#if defined THREAD_SELF && defined INIT_THREAD_SELF +# ifndef USE_TLS +# define manager_thread (&__pthread_manager_thread) +# endif +# define CHECK_THREAD_SELF(self) \ +do { \ + if (self == manager_thread) \ + { \ + /* A new thread might get a cancel signal before it is fully \ + initialized, so that the thread register might still point to the \ + manager thread. Double check that this is really the manager \ + thread. */ \ + pthread_descr real_self = __pthread_self_stack(); \ + if (real_self != manager_thread) \ + { \ + /* Oops, thread_self() isn't working yet.. */ \ + self = real_self; \ + INIT_THREAD_SELF(self, self->p_nr); \ + } \ + } \ +} while (0) +#else +# define CHECK_THREAD_SELF(self) do { } while (0) +#endif + /* The wrapper around user-provided signal handlers */ void __pthread_sighandler(int signo, SIGCONTEXT ctx) @@ -23,6 +48,7 @@ void __pthread_sighandler(int signo, SIG pthread_descr self; char * in_sighandler; self = thread_self(); + CHECK_THREAD_SELF(self); /* If we're in a sigwait operation, just record the signal received and return without calling the user's handler */ if (THREAD_GETMEM(self, p_sigwaiting)) { @@ -47,6 +73,7 @@ void __pthread_sighandler_rt(int signo, pthread_descr self; char * in_sighandler; self = thread_self(); + CHECK_THREAD_SELF(self); /* If we're in a sigwait operation, just record the signal received and return without calling the user's handler */ if (THREAD_GETMEM(self, p_sigwaiting)) { Jakub
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |