fix minor bugs due to incorrect threaded-predicate semantics
authorRich Felker <dalias@aerifal.cx>
Thu, 21 Apr 2011 01:41:45 +0000 (21:41 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 21 Apr 2011 01:41:45 +0000 (21:41 -0400)
some functions that should have been testing whether pthread_self()
had been called and initialized the thread pointer were instead
testing whether pthread_create() had been called and actually made the
program "threaded". while it's unlikely any mismatch would occur in
real-world problems, this could have introduced subtle bugs. now, we
store the address of the main thread's thread descriptor in the libc
structure and use its presence as a flag that the thread register is
initialized. note that after fork, the calling thread (not necessarily
the original main thread) is the new main thread.

src/internal/libc.h
src/process/fork.c
src/thread/pthread_self.c
src/thread/pthread_setcancelstate.c

index 06ba73e7fb685bb0fffcd6398e87d06c1d5a6765..638ea5270e38f5a449011edac0df9762b3a05865 100644 (file)
@@ -16,6 +16,7 @@ struct __libc {
        volatile int threads_minus_1;
        int ofl_lock;
        FILE *ofl_head;
+       void *main_thread;
 };
 
 
index bcd47c97a6e117e16c9c4bf534a26b56edc6aec8..a04e8929a70e10ce7e32e3e44834ebb9ab51e049 100644 (file)
@@ -8,10 +8,11 @@ pid_t fork(void)
        pid_t ret;
        if (libc.fork_handler) libc.fork_handler(-1);
        ret = syscall(SYS_fork);
-       if (libc.threaded && !ret) {
+       if (libc.main_thread && !ret) {
                pthread_t self = __pthread_self();
                self->tid = self->pid = syscall(SYS_getpid);
                libc.threads_minus_1 = 0;
+               libc.main_thread = self;
        }
        if (libc.fork_handler) libc.fork_handler(!ret);
        return ret;
index e8bb9181502afc87388d27b8ddbdc6658bad24d4..55d20c9f8a9ac759a6747cac9e073a170db24c22 100644 (file)
@@ -6,7 +6,6 @@ static struct pthread main_thread;
 static const void *dummy[1] = { 0 };
 weak_alias(dummy, __pthread_tsd_main);
 
-#undef errno
 static int *errno_location()
 {
        return __pthread_self()->errno_ptr;
@@ -14,11 +13,10 @@ static int *errno_location()
 
 static int init_main_thread()
 {
+       if (__set_thread_area(&main_thread) < 0) return -1;
        main_thread.canceldisable = libc.canceldisable;
        main_thread.tsd = (void **)__pthread_tsd_main;
-       main_thread.self = &main_thread;
-       if (__set_thread_area(&main_thread) < 0)
-               return -1;
+       main_thread.self = libc.main_thread = &main_thread;
        main_thread.errno_ptr = __errno_location();
        libc.errno_location = errno_location;
        main_thread.tid = main_thread.pid = 
index ebb6eba43d0a47ca61a62febfa939f73f031dd83..ba2b231190436076b1d200bc76fa6e2c5dec9443 100644 (file)
@@ -3,7 +3,7 @@
 int pthread_setcancelstate(int new, int *old)
 {
        if (new > 1U) return EINVAL;
-       if (libc.threaded) {
+       if (libc.main_thread) {
                struct pthread *self = __pthread_self();
                if (old) *old = self->canceldisable;
                self->canceldisable = new;