Browse Source

fix minor bugs due to incorrect threaded-predicate semantics

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.
Rich Felker 14 years ago
parent
commit
870cc67977
4 changed files with 6 additions and 6 deletions
  1. 1 0
      src/internal/libc.h
  2. 2 1
      src/process/fork.c
  3. 2 4
      src/thread/pthread_self.c
  4. 1 1
      src/thread/pthread_setcancelstate.c

+ 1 - 0
src/internal/libc.h

@@ -16,6 +16,7 @@ struct __libc {
 	volatile int threads_minus_1;
 	int ofl_lock;
 	FILE *ofl_head;
+	void *main_thread;
 };
 
 

+ 2 - 1
src/process/fork.c

@@ -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;

+ 2 - 4
src/thread/pthread_self.c

@@ -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 = 

+ 1 - 1
src/thread/pthread_setcancelstate.c

@@ -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;