From aa168ed2cd0614afa7503e3b0eb2b1e38b43384a Mon Sep 17 00:00:00 2001 From: Michael MacInnis <Michael.P.MacInnis@gmail.com> Date: Thu, 11 Sep 2014 18:39:51 -0700 Subject: [PATCH] syscall: SysProcAttr job control changes 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 | 40 +++++++++++++++++++++++++++++++++++++-- src/syscall/exec_linux.go | 40 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go index ff78f197f1..7c2c1f7071 100644 --- a/src/syscall/exec_bsd.go +++ b/src/syscall/exec_bsd.go @@ -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 diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index f27950f730..f61dfc424a 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -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 -- 2.30.9