Browse Source

fix deadlock in synccall after threaded fork

synccall may be called by AS-safe functions such as setuid/setgid after
fork. although fork() resets libc.threads_minus_one, causing synccall to
take the single-threaded path, synccall still takes the thread list
lock. This lock may be held by another thread if for example fork()
races with pthread_create(). After fork(), the value of the lock is
meaningless, so clear it.

maintainer's note: commit 8f11e6127fe93093f81a52b15bb1537edc3fc8af and
e4235d70672d9751d7718ddc2b52d0b426430768 introduced this regression.
the state protected by this lock is the linked list, which is entirely
replaced in the child path of fork (next=prev=self), so resetting it
is semantically sound.
Samuel Holland 5 years ago
parent
commit
84ebec6cee
1 changed files with 1 additions and 0 deletions
  1. 1 0
      src/process/fork.c

+ 1 - 0
src/process/fork.c

@@ -28,6 +28,7 @@ pid_t fork(void)
 		self->robust_list.off = 0;
 		self->robust_list.pending = 0;
 		self->next = self->prev = self;
+		__thread_list_lock = 0;
 		libc.threads_minus_1 = 0;
 	}
 	__restore_sigs(&set);