summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread
diff options
context:
space:
mode:
authorjasone <jasone@FreeBSD.org>2001-08-16 06:31:32 +0000
committerjasone <jasone@FreeBSD.org>2001-08-16 06:31:32 +0000
commit6e7ccfd0939ba6aaace23d8e2434af0d3dd8ab28 (patch)
tree58d56e8f03dd7d3a15b34ecf3a5680c7e056fa65 /lib/libpthread/thread
parentcd3f3aab8e337abe90764fb04a24c977624fdecd (diff)
downloadFreeBSD-src-6e7ccfd0939ba6aaace23d8e2434af0d3dd8ab28.zip
FreeBSD-src-6e7ccfd0939ba6aaace23d8e2434af0d3dd8ab28.tar.gz
Fix a bug in canceling joining threads.
Do not detach canceled threads. Reported by: Arno Klaassen <arno@heho.snv.jussieu.fr> Collaboration with: deischen
Diffstat (limited to 'lib/libpthread/thread')
-rw-r--r--lib/libpthread/thread/thr_cancel.c16
-rw-r--r--lib/libpthread/thread/thr_join.c3
-rw-r--r--lib/libpthread/thread/thr_private.h1
3 files changed, 18 insertions, 2 deletions
diff --git a/lib/libpthread/thread/thr_cancel.c b/lib/libpthread/thread/thr_cancel.c
index 2af3db6..7f40e36 100644
--- a/lib/libpthread/thread/thr_cancel.c
+++ b/lib/libpthread/thread/thr_cancel.c
@@ -64,9 +64,23 @@ _pthread_cancel(pthread_t pthread)
break;
case PS_JOIN:
+ /*
+ * Disconnect the thread from the joinee and
+ * detach:
+ */
+ if (pthread->data.thread != NULL) {
+ pthread->data.thread->joiner = NULL;
+ pthread_detach((pthread_t)
+ pthread->data.thread);
+ }
+ pthread->cancelflags |= PTHREAD_CANCELLING;
+ PTHREAD_NEW_STATE(pthread, PS_RUNNING);
+ break;
+
case PS_SUSPENDED:
if (pthread->suspended == SUSP_NO ||
pthread->suspended == SUSP_YES ||
+ pthread->suspended == SUSP_JOIN ||
pthread->suspended == SUSP_NOWAIT) {
/*
* This thread isn't in any scheduling
@@ -189,7 +203,6 @@ _pthread_testcancel(void)
*/
curthread->cancelflags &= ~PTHREAD_CANCELLING;
_thread_exit_cleanup();
- pthread_detach((pthread_t)curthread);
pthread_exit(PTHREAD_CANCELED);
PANIC("cancel");
}
@@ -226,7 +239,6 @@ finish_cancellation(void *arg)
if ((curthread->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
curthread->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
- pthread_detach((pthread_t)curthread);
pthread_exit(PTHREAD_CANCELED);
}
}
diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c
index 968c24c..454c79a 100644
--- a/lib/libpthread/thread/thr_join.c
+++ b/lib/libpthread/thread/thr_join.c
@@ -121,6 +121,9 @@ _pthread_join(pthread_t pthread, void **thread_return)
/* Set the running thread to be the joiner: */
pthread->joiner = curthread;
+ /* Keep track of which thread we're joining to: */
+ curthread->data.thread = pthread;
+
/* Schedule the next thread: */
_thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__);
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index 2bfac78..cc3ec79 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -575,6 +575,7 @@ union pthread_wait_data {
FILE *fp;
struct pthread_poll_data *poll_data;
spinlock_t *spinlock;
+ struct pthread *thread;
};
/*
OpenPOWER on IntegriCloud