fix usage of locks with vfork
authorRich Felker <dalias@aerifal.cx>
Fri, 19 Oct 2012 19:02:37 +0000 (15:02 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 19 Oct 2012 19:02:37 +0000 (15:02 -0400)
__release_ptc() is only valid in the parent; if it's performed in the
child, the lock will be unlocked early then double-unlocked later,
corrupting the lock state.

src/process/posix_spawn.c
src/process/system.c
src/stdio/popen.c

index c3e800b..5eb516b 100644 (file)
@@ -35,9 +35,9 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path,
 
        __acquire_ptc();
        pid = __vfork();
 
        __acquire_ptc();
        pid = __vfork();
-       __release_ptc();
 
        if (pid) {
 
        if (pid) {
+               __release_ptc();
                sigprocmask(SIG_SETMASK, &oldmask, 0);
                if (pid < 0) return -pid;
                *res = pid;
                sigprocmask(SIG_SETMASK, &oldmask, 0);
                if (pid < 0) return -pid;
                *res = pid;
index c8f2600..ebe207f 100644 (file)
@@ -29,7 +29,8 @@ int system(const char *cmd)
 
        __acquire_ptc();
        pid = __vfork();
 
        __acquire_ptc();
        pid = __vfork();
-       __release_ptc();
+
+       if (pid) __release_ptc();
 
        if (pid > 0) {
                sigset_t new = old;
 
        if (pid > 0) {
                sigset_t new = old;
index 0c9f24e..5a47509 100644 (file)
@@ -38,9 +38,9 @@ FILE *popen(const char *cmd, const char *mode)
        
        __acquire_ptc();
        pid = __vfork();
        
        __acquire_ptc();
        pid = __vfork();
-       __release_ptc();
 
        if (pid) {
 
        if (pid) {
+               __release_ptc();
                __syscall(SYS_close, p[1-op]);
                sigprocmask(SIG_BLOCK, SIGALL_SET, &old);
                if (pid < 0) {
                __syscall(SYS_close, p[1-op]);
                sigprocmask(SIG_BLOCK, SIGALL_SET, &old);
                if (pid < 0) {