summaryrefslogtreecommitdiff
path: root/devel/linuxthreads
diff options
context:
space:
mode:
authorTor Egge <tegge@FreeBSD.org>2002-04-22 16:50:02 +0000
committerTor Egge <tegge@FreeBSD.org>2002-04-22 16:50:02 +0000
commitb20aef1bb8eaa03b0be7a221686d8b75b1b974a4 (patch)
tree4386148ed16f1b41259c01e440fbd53d071ca8cf /devel/linuxthreads
parentChange 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/Makefile2
-rw-r--r--devel/linuxthreads/files/patch-aa94
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