mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
fix posix_spawn interaction with fork and abort by taking lock
this change prevents the child created concurrently with abort from seeing the SIGABRT disposition change from SIG_IGN to SIG_DFL (other changes are not visible anyway) and prevents leaking the write end of the child pipe to children created by fork in another thread, which may block return of posix_spawn indefinitely if the forked child does not exit or exec. along with other changes, this suggests that __abort_lock should perhaps eventually be renamed to reflect that it's becoming a broader lock on related "process lifetime" state.
This commit is contained in:
parent
25ea9f712c
commit
b7bc966522
1 changed files with 13 additions and 3 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include "syscall.h"
|
||||
#include "lock.h"
|
||||
#include "pthread_impl.h"
|
||||
#include "fdop.h"
|
||||
|
||||
|
@ -170,9 +171,6 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
|
|||
int ec=0, cs;
|
||||
struct args args;
|
||||
|
||||
if (pipe2(args.p, O_CLOEXEC))
|
||||
return errno;
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
|
||||
|
||||
args.path = path;
|
||||
|
@ -182,9 +180,20 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
|
|||
args.envp = envp;
|
||||
pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
|
||||
|
||||
/* The lock guards both against seeing a SIGABRT disposition change
|
||||
* by abort and against leaking the pipe fd to fork-without-exec. */
|
||||
LOCK(__abort_lock);
|
||||
|
||||
if (pipe2(args.p, O_CLOEXEC)) {
|
||||
UNLOCK(__abort_lock);
|
||||
ec = errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pid = __clone(child, stack+sizeof stack,
|
||||
CLONE_VM|CLONE_VFORK|SIGCHLD, &args);
|
||||
close(args.p[1]);
|
||||
UNLOCK(__abort_lock);
|
||||
|
||||
if (pid > 0) {
|
||||
if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0;
|
||||
|
@ -197,6 +206,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
|
|||
|
||||
if (!ec && res) *res = pid;
|
||||
|
||||
fail:
|
||||
pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
|
||||
pthread_setcancelstate(cs, 0);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue