Selaa lähdekoodia

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 vuotta sitten
vanhempi
sitoutus
870cc67977

+ 1 - 0
src/internal/libc.h

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

+ 2 - 1
src/process/fork.c

@@ -8,10 +8,11 @@ pid_t fork(void)
 	pid_t ret;
 	pid_t ret;
 	if (libc.fork_handler) libc.fork_handler(-1);
 	if (libc.fork_handler) libc.fork_handler(-1);
 	ret = syscall(SYS_fork);
 	ret = syscall(SYS_fork);
-	if (libc.threaded && !ret) {
+	if (libc.main_thread && !ret) {
 		pthread_t self = __pthread_self();
 		pthread_t self = __pthread_self();
 		self->tid = self->pid = syscall(SYS_getpid);
 		self->tid = self->pid = syscall(SYS_getpid);
 		libc.threads_minus_1 = 0;
 		libc.threads_minus_1 = 0;
+		libc.main_thread = self;
 	}
 	}
 	if (libc.fork_handler) libc.fork_handler(!ret);
 	if (libc.fork_handler) libc.fork_handler(!ret);
 	return 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 };
 static const void *dummy[1] = { 0 };
 weak_alias(dummy, __pthread_tsd_main);
 weak_alias(dummy, __pthread_tsd_main);
 
 
-#undef errno
 static int *errno_location()
 static int *errno_location()
 {
 {
 	return __pthread_self()->errno_ptr;
 	return __pthread_self()->errno_ptr;
@@ -14,11 +13,10 @@ static int *errno_location()
 
 
 static int init_main_thread()
 static int init_main_thread()
 {
 {
+	if (__set_thread_area(&main_thread) < 0) return -1;
 	main_thread.canceldisable = libc.canceldisable;
 	main_thread.canceldisable = libc.canceldisable;
 	main_thread.tsd = (void **)__pthread_tsd_main;
 	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();
 	main_thread.errno_ptr = __errno_location();
 	libc.errno_location = errno_location;
 	libc.errno_location = errno_location;
 	main_thread.tid = main_thread.pid = 
 	main_thread.tid = main_thread.pid = 

+ 1 - 1
src/thread/pthread_setcancelstate.c

@@ -3,7 +3,7 @@
 int pthread_setcancelstate(int new, int *old)
 int pthread_setcancelstate(int new, int *old)
 {
 {
 	if (new > 1U) return EINVAL;
 	if (new > 1U) return EINVAL;
-	if (libc.threaded) {
+	if (libc.main_thread) {
 		struct pthread *self = __pthread_self();
 		struct pthread *self = __pthread_self();
 		if (old) *old = self->canceldisable;
 		if (old) *old = self->canceldisable;
 		self->canceldisable = new;
 		self->canceldisable = new;