diff options
author | Tor Egge <tegge@FreeBSD.org> | 2002-04-22 16:50:02 +0000 |
---|---|---|
committer | Tor Egge <tegge@FreeBSD.org> | 2002-04-22 16:50:02 +0000 |
commit | b20aef1bb8eaa03b0be7a221686d8b75b1b974a4 (patch) | |
tree | 4386148ed16f1b41259c01e440fbd53d071ca8cf /devel/linuxthreads | |
parent | Change to vi:ts=8. (diff) |
Fix hang caused by a thread calling exit():
- Block cancel signal while creating new thread to avoid losing
the signal.
- Terminate the process with _exit(1) if it's unsafe to continue
calling atexit functions and destructors.
Diffstat (limited to 'devel/linuxthreads')
-rw-r--r-- | devel/linuxthreads/Makefile | 2 | ||||
-rw-r--r-- | devel/linuxthreads/files/patch-aa | 94 |
2 files changed, 75 insertions, 21 deletions
diff --git a/devel/linuxthreads/Makefile b/devel/linuxthreads/Makefile index 2f7afeaf5b0d..7b423077e28b 100644 --- a/devel/linuxthreads/Makefile +++ b/devel/linuxthreads/Makefile @@ -7,7 +7,7 @@ PORTNAME= linuxthreads PORTVERSION= 2.2.3 -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= devel MASTER_SITES= ${MASTER_SITE_GNU} MASTER_SITE_SUBDIR= glibc diff --git a/devel/linuxthreads/files/patch-aa b/devel/linuxthreads/files/patch-aa index ef2383e4861d..eaa883bb2c85 100644 --- a/devel/linuxthreads/files/patch-aa +++ b/devel/linuxthreads/files/patch-aa @@ -466,7 +466,26 @@ diff -ru ../../work/linuxthreads-2.2.3/manager.c ./manager.c if (pid == 0) { #ifdef NEED_SEPARATE_REGISTER_STACK -@@ -738,6 +750,7 @@ +@@ -628,9 +640,18 @@ + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); + #else ++ /* Block all signals during thread creation to avoid new thread ++ * overwriting thread manager stack. ++ */ ++ sigset_t allblock_mask; ++ sigset_t oldmask; ++ ++ sigfillset(&allblock_mask); ++ sigprocmask(SIG_SETMASK, &allblock_mask, &oldmask); + pid = __clone(pthread_start_thread, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); ++ sigprocmask(SIG_SETMASK, &oldmask, NULL); + #endif /* !NEED_SEPARATE_REGISTER_STACK */ + } + /* Check if cloning succeeded */ +@@ -738,6 +759,7 @@ /* Mark thread as exited, and if detached, free its resources */ __pthread_lock(th->p_lock, NULL); th->p_exited = 1; @@ -474,7 +493,7 @@ diff -ru ../../work/linuxthreads-2.2.3/manager.c ./manager.c /* If we have to signal this event do it now. */ if (th->p_report_events) { -@@ -757,6 +770,7 @@ +@@ -757,6 +779,7 @@ __linuxthreads_reap_event(); } } @@ -482,21 +501,33 @@ diff -ru ../../work/linuxthreads-2.2.3/manager.c ./manager.c detached = th->p_detached; __pthread_unlock(th->p_lock); if (detached) -@@ -834,10 +848,14 @@ +@@ -834,10 +857,16 @@ /* Process-wide exit() */ +extern int __pthread_exit_requested_bymainthread; ++extern int __pthread_exit_alone; + static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) { pthread_descr th; __pthread_exit_requested = 1; ++ __pthread_exit_alone = 1; + if (issuing_thread == __pthread_main_thread) + __pthread_exit_requested_bymainthread = 1; __pthread_exit_code = exitcode; /* Send the CANCEL signal to all running threads, including the main thread, but excluding the thread from which the exit request originated +@@ -846,6 +875,9 @@ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { ++ /* Cancelled thread might have been in critical region unless terminated */ ++ if (th->p_terminated == 0) ++ __pthread_exit_alone = 0; + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies diff -ru ../../work/linuxthreads-2.2.3/ptfork.c ./ptfork.c --- ../../work/linuxthreads-2.2.3/ptfork.c Sun Jan 7 04:35:20 2001 +++ ./ptfork.c Thu Jun 7 22:59:29 2001 @@ -597,15 +628,16 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ 0, /* char p_woken_by_cancel */ 0, /* char p_condvar_avail */ -@@ -185,6 +195,7 @@ +@@ -185,6 +195,8 @@ /* For process-wide exit() */ int __pthread_exit_requested; +int __pthread_exit_requested_bymainthread = 0; ++int __pthread_exit_alone = 1; int __pthread_exit_code; /* Maximum stack size. */ -@@ -216,11 +227,7 @@ +@@ -216,11 +228,7 @@ /* Forward declarations */ @@ -618,7 +650,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c static void pthread_handle_sigcancel(int sig); static void pthread_handle_sigrestart(int sig); static void pthread_handle_sigdebug(int sig); -@@ -238,8 +245,8 @@ +@@ -238,8 +246,8 @@ #ifndef __SIGRTMIN static int current_rtmin = -1; static int current_rtmax = -1; @@ -629,7 +661,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c int __pthread_sig_debug; #else static int current_rtmin; -@@ -250,8 +257,8 @@ +@@ -250,8 +258,8 @@ int __pthread_sig_cancel = __SIGRTMIN + 1; int __pthread_sig_debug = __SIGRTMIN + 2; #else @@ -640,7 +672,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c int __pthread_sig_debug; #endif -@@ -348,26 +355,17 @@ +@@ -348,26 +356,17 @@ static int is_smp_system (void) { @@ -676,7 +708,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c } -@@ -448,13 +446,7 @@ +@@ -448,13 +447,7 @@ /* Register an exit function to kill all other threads. */ /* Do it early so that user-registered atexit functions are called before pthread_*exit_process. */ @@ -691,7 +723,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c /* How many processors. */ __pthread_smp_kernel = is_smp_system (); } -@@ -502,12 +494,6 @@ +@@ -502,12 +495,6 @@ int pid; struct pthread_request request; @@ -704,7 +736,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c if (__pthread_max_stacksize == 0) __pthread_init_max_stacksize (); /* If basic initialization not done yet (e.g. we're called from a -@@ -525,6 +511,7 @@ +@@ -525,6 +512,7 @@ } /* Start the thread manager */ pid = 0; @@ -712,7 +744,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c if (__builtin_expect (__pthread_initial_thread.p_report_events, 0)) { /* It's a bit more complicated. We have to report the creation of -@@ -572,17 +559,20 @@ +@@ -572,17 +560,20 @@ __pthread_unlock(__pthread_manager_thread.p_lock); } } @@ -735,7 +767,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c (void *)(long)manager_pipe[0]); #endif } -@@ -715,7 +705,7 @@ +@@ -715,7 +706,7 @@ __pthread_unlock(&handle->h_lock); return errno; } @@ -744,7 +776,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c __pthread_unlock(&handle->h_lock); if (__pthread_manager_request >= 0) __pthread_manager_adjust_prio(th->p_priority); -@@ -751,7 +741,7 @@ +@@ -751,7 +742,7 @@ /* Process-wide exit() request */ @@ -753,7 +785,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c { if (__builtin_expect (__pthread_manager_request, 0) >= 0) { struct pthread_request request; -@@ -759,7 +749,7 @@ +@@ -759,7 +750,7 @@ request.req_thread = self; request.req_kind = REQ_PROCESS_EXIT; @@ -762,7 +794,29 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c __libc_write(__pthread_manager_request, (char *) &request, sizeof(request)); suspend(self); -@@ -774,19 +764,6 @@ +@@ -768,25 +759,28 @@ + if (self == __pthread_main_thread) + { + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); ++ /* ++ * If other threads have been canceled then proper cleanup ++ * cannot be performed since a canceled thread might have ++ * been inside a critical region of code with a spinlock ++ * held, a system mutex held, or a mutex partially held. ++ */ ++ if (__pthread_exit_alone == 0) ++ _exit(1); + free (__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } ++ /* ++ * If other threads have been canceled then proper cleanup ++ * cannot be performed since a canceled thread might have ++ * been inside a critical region of code with a spinlock ++ * held, a system mutex held, or a mutex partially held. ++ */ ++ if (__pthread_exit_alone == 0) ++ _exit(1); } } @@ -782,7 +836,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c /* The handler for the RESTART signal just records the signal received in the thread descriptor, and optionally performs a siglongjmp -@@ -818,6 +795,9 @@ +@@ -818,6 +812,9 @@ if (__builtin_expect (__pthread_exit_requested, 0)) { /* Main thread should accumulate times for thread manager and its children, so that timings for main thread account for all threads. */ @@ -792,7 +846,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c if (self == __pthread_main_thread) waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); _exit(__pthread_exit_code); -@@ -894,7 +874,7 @@ +@@ -894,7 +891,7 @@ { struct sigaction sa; /* Terminate all other threads and thread manager */ @@ -801,7 +855,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c /* Make current thread the main thread in case the calling thread changes its mind, does not exec(), and creates new threads instead. */ __pthread_reset_main_thread(); -@@ -967,7 +947,7 @@ +@@ -967,7 +964,7 @@ __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) { sigset_t unblock, initial_mask; @@ -810,7 +864,7 @@ diff -ru ../../work/linuxthreads-2.2.3/pthread.c ./pthread.c sigjmp_buf jmpbuf; if (atomic_decrement(&self->p_resume_count) == 0) { -@@ -1131,3 +1111,17 @@ +@@ -1131,3 +1128,17 @@ static const int *const __pthread_require_wrappers = &__pthread_provide_wrappers; #endif |