mirror of
git://sourceware.org/git/glibc.git
synced 2025-01-12 12:07:12 +08:00
Update.
* manager.c (pthread_exited): If thread is not detached put it on special list. (pthread_handle_free): If thread is not on list with living threads search on list with detached threads.
This commit is contained in:
parent
9c3a54d42a
commit
026d50118f
@ -1,5 +1,10 @@
|
||||
1998-06-26 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* manager.c (pthread_exited): If thread is not detached put it on
|
||||
special list.
|
||||
(pthread_handle_free): If thread is not on list with living threads
|
||||
search on list with detached threads.
|
||||
|
||||
* sysdeps/pthread/pthread.h (PTHREAD_RWLOCK_INITIALIZER): Correct
|
||||
for new definition of pthread_rwlock_t.
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h> /* for select */
|
||||
#include <sys/poll.h> /* for poll */
|
||||
#include <sys/mman.h> /* for mmap */
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h> /* for waitpid macros */
|
||||
@ -37,6 +37,12 @@
|
||||
struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
|
||||
{ { LOCK_INITIALIZER, &__pthread_initial_thread, 0}, /* All NULLs */ };
|
||||
|
||||
/* This is a list of terminated, but not detached threads. This can happen
|
||||
when pthread_join() is called and the pthread_reap_children() function
|
||||
removes the thread from the live list before processing the FREE_REQ
|
||||
request. */
|
||||
static pthread_descr non_detached;
|
||||
|
||||
/* Indicate whether at least one thread has a user-defined stack (if 1),
|
||||
or if all threads have stacks supplied by LinuxThreads (if 0). */
|
||||
int __pthread_nonstandard_stacks = 0;
|
||||
@ -87,9 +93,8 @@ static void pthread_kill_all_threads(int sig, int main_thread_also);
|
||||
int __pthread_manager(void *arg)
|
||||
{
|
||||
int reqfd = (int)arg;
|
||||
struct pollfd ufd;
|
||||
sigset_t mask;
|
||||
fd_set readfds;
|
||||
struct timeval timeout;
|
||||
int n;
|
||||
struct pthread_request request;
|
||||
|
||||
@ -112,13 +117,11 @@ int __pthread_manager(void *arg)
|
||||
/* Synchronize debugging of the thread manager */
|
||||
n = __libc_read(reqfd, (char *)&request, sizeof(request));
|
||||
ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
|
||||
ufd.fd = reqfd;
|
||||
ufd.events = POLLIN;
|
||||
/* Enter server loop */
|
||||
while(1) {
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(reqfd, &readfds);
|
||||
timeout.tv_sec = 2;
|
||||
timeout.tv_usec = 0;
|
||||
n = __select(reqfd + 1, &readfds, NULL, NULL, &timeout);
|
||||
n = __poll(&ufd, 1, 2000);
|
||||
|
||||
/* Check for termination of the main thread */
|
||||
if (getppid() == 1) {
|
||||
@ -131,7 +134,7 @@ int __pthread_manager(void *arg)
|
||||
pthread_reap_children();
|
||||
}
|
||||
/* Read and execute request */
|
||||
if (n == 1 && FD_ISSET(reqfd, &readfds)) {
|
||||
if (n == 1 && (ufd.revents & POLLIN)) {
|
||||
n = __libc_read(reqfd, (char *)&request, sizeof(request));
|
||||
ASSERT(n == sizeof(request));
|
||||
switch(request.req_kind) {
|
||||
@ -401,7 +404,16 @@ static void pthread_exited(pid_t pid)
|
||||
th->p_exited = 1;
|
||||
detached = th->p_detached;
|
||||
__pthread_unlock(th->p_lock);
|
||||
if (detached) pthread_free(th);
|
||||
if (detached)
|
||||
pthread_free(th);
|
||||
else {
|
||||
/* Enqueue in the detached list. */
|
||||
th->p_nextlive = non_detached;
|
||||
if (non_detached != NULL)
|
||||
non_detached->p_prevlive = th;
|
||||
th->p_prevlive = NULL;
|
||||
non_detached = th;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -436,7 +448,6 @@ static void pthread_reap_children(void)
|
||||
static void pthread_handle_free(pthread_descr th)
|
||||
{
|
||||
pthread_descr t;
|
||||
|
||||
/* Check that the thread th is still there -- pthread_reap_children
|
||||
might have deallocated it already */
|
||||
t = __pthread_main_thread;
|
||||
@ -444,8 +455,29 @@ static void pthread_handle_free(pthread_descr th)
|
||||
if (t == th) break;
|
||||
t = t->p_nextlive;
|
||||
} while (t != __pthread_main_thread);
|
||||
if (t != th) return;
|
||||
if (t != th) {
|
||||
/* Hum, it might be that the thread already was dequeued but
|
||||
wasn't detached. In the case the thread is already detached
|
||||
and we cannot find it this is a user bug but we must be
|
||||
gracious. */
|
||||
t = non_detached;
|
||||
while (t != NULL) {
|
||||
if (t == th) break;
|
||||
t = t->p_nextlive;
|
||||
}
|
||||
if (t == th) {
|
||||
if (th->p_prevlive == NULL)
|
||||
non_detached = th->p_nextlive;
|
||||
else
|
||||
th->p_prevlive->p_nextlive = th->p_nextlive;
|
||||
if (th->p_nextlive != NULL)
|
||||
th->p_nextlive->p_prevlive = th->p_prevlive;
|
||||
|
||||
/* Finally free it. */
|
||||
pthread_free (th);
|
||||
}
|
||||
return;
|
||||
}
|
||||
__pthread_lock(th->p_lock);
|
||||
if (th->p_exited) {
|
||||
__pthread_unlock(th->p_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user