]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: SysProcAttr job control changes
authorMichael MacInnis <Michael.P.MacInnis@gmail.com>
Fri, 12 Sep 2014 01:39:51 +0000 (18:39 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 12 Sep 2014 01:39:51 +0000 (18:39 -0700)
Making the child's process group the foreground process group and
placing the child in a specific process group involves co-ordination
between the parent and child that must be done post-fork but pre-exec.

LGTM=iant
R=golang-codereviews, gobot, iant, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/131750044

src/syscall/exec_bsd.go
src/syscall/exec_linux.go

index ff78f197f1fb30af337e1618264f56aa701a1302..7c2c1f7071a8094a43ff89ccb73a42ea103849ef 100644 (file)
@@ -19,6 +19,8 @@ type SysProcAttr struct {
        Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
        Setctty    bool        // Set controlling terminal to fd 0
        Noctty     bool        // Detach fd 0 from controlling terminal
+       Foreground bool        // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
+       Joinpgrp   int         // If != 0, child's process group ID. (Setpgid must not be set)
 }
 
 // Implemented in runtime package.
@@ -79,7 +81,22 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        if r1 != 0 {
                // parent; return PID
                runtime_AfterFork()
-               return int(r1), 0
+               pid = int(r1)
+
+               if sys.Joinpgrp != 0 {
+                       // Place the child in the specified process group.
+                       RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
+               } else if sys.Foreground || sys.Setpgid {
+                       // Place the child in a new process group.
+                       RawSyscall(SYS_SETPGID, 0, 0, 0)
+
+                       if sys.Foreground {
+                               // Set new foreground process group.
+                               RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
+                       }
+               }
+
+               return pid, 0
        }
 
        // Fork succeeded, now in child.
@@ -101,11 +118,30 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // Set process group
-       if sys.Setpgid {
+       if sys.Joinpgrp != 0 {
+               // Place the child in the specified process group.
+               _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
+               if err1 != 0 {
+                       goto childerror
+               }
+       } else if sys.Foreground || sys.Setpgid {
+               // Place the child in a new process group.
                _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
                if err1 != 0 {
                        goto childerror
                }
+
+               if sys.Foreground {
+                       r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
+
+                       pid := int(r1)
+
+                       // Set new foreground process group.
+                       _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
+                       if err1 != 0 {
+                               goto childerror
+                       }
+               }
        }
 
        // Chroot
index f27950f730c76274dc0ad2585c7b1b2f262167c3..f61dfc424a08a47a8621eac0059e36ca80c9eb43 100644 (file)
@@ -21,6 +21,8 @@ type SysProcAttr struct {
        Ctty       int         // Controlling TTY fd (Linux only)
        Pdeathsig  Signal      // Signal that the process will get when its parent dies (Linux only)
        Cloneflags uintptr     // Flags for clone calls (Linux only)
+       Foreground bool        // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
+       Joinpgrp   int         // If != 0, child's process group ID. (Setpgid must not be set)
 }
 
 // Implemented in runtime package.
@@ -71,7 +73,22 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        if r1 != 0 {
                // parent; return PID
                runtime_AfterFork()
-               return int(r1), 0
+               pid = int(r1)
+
+               if sys.Joinpgrp != 0 {
+                       // Place the child in the specified process group.
+                       RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
+               } else if sys.Foreground || sys.Setpgid {
+                       // Place the child in a new process group.
+                       RawSyscall(SYS_SETPGID, 0, 0, 0)
+
+                       if sys.Foreground {
+                               // Set new foreground process group.
+                               RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
+                       }
+               }
+
+               return pid, 0
        }
 
        // Fork succeeded, now in child.
@@ -113,11 +130,30 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
        }
 
        // Set process group
-       if sys.Setpgid {
+       if sys.Joinpgrp != 0 {
+               // Place the child in the specified process group.
+               _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
+               if err1 != 0 {
+                       goto childerror
+               }
+       } else if sys.Foreground || sys.Setpgid {
+               // Place the child in a new process group.
                _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
                if err1 != 0 {
                        goto childerror
                }
+
+               if sys.Foreground {
+                       r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
+
+                       pid := int(r1)
+
+                       // Set new foreground process group.
+                       _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
+                       if err1 != 0 {
+                               goto childerror
+                       }
+               }
        }
 
        // Chroot