9da92cbda9
Only build net/hook_cloexec.go on GNU/Linux and FreeBSD, because those are the only systems with accept4. Add syscall/libcall_bsd.go to define sendfile for *BSD and Solaris. Revert tcpsockopt_solaris.go back to the earlier version, so that it works on Solaris 10. Always pass the address of a Pid_t value to TIOCGPGRP and TIOCSPGRP. Include <unistd.h> in runtime/go-varargs.c. Reviewed-on: https://go-review.googlesource.com/16719 From-SVN: r229880
216 lines
3.9 KiB
Go
216 lines
3.9 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
|
|
|
package syscall_test
|
|
|
|
import (
|
|
"internal/testenv"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"syscall"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
type command struct {
|
|
pipe io.WriteCloser
|
|
proc *exec.Cmd
|
|
test *testing.T
|
|
}
|
|
|
|
func (c *command) Info() (pid, pgrp int) {
|
|
pid = c.proc.Process.Pid
|
|
|
|
pgrp, err := syscall.Getpgid(pid)
|
|
if err != nil {
|
|
c.test.Fatal(err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *command) Start() {
|
|
if err := c.proc.Start(); err != nil {
|
|
c.test.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (c *command) Stop() {
|
|
c.pipe.Close()
|
|
if err := c.proc.Wait(); err != nil {
|
|
c.test.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func create(t *testing.T) *command {
|
|
testenv.MustHaveExec(t)
|
|
|
|
proc := exec.Command("cat")
|
|
stdin, err := proc.StdinPipe()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
return &command{stdin, proc, t}
|
|
}
|
|
|
|
func parent() (pid, pgrp int) {
|
|
return syscall.Getpid(), syscall.Getpgrp()
|
|
}
|
|
|
|
func TestZeroSysProcAttr(t *testing.T) {
|
|
ppid, ppgrp := parent()
|
|
|
|
cmd := create(t)
|
|
|
|
cmd.Start()
|
|
defer cmd.Stop()
|
|
|
|
cpid, cpgrp := cmd.Info()
|
|
|
|
if cpid == ppid {
|
|
t.Fatalf("Parent and child have the same process ID")
|
|
}
|
|
|
|
if cpgrp != ppgrp {
|
|
t.Fatalf("Child is not in parent's process group")
|
|
}
|
|
}
|
|
|
|
func TestSetpgid(t *testing.T) {
|
|
ppid, ppgrp := parent()
|
|
|
|
cmd := create(t)
|
|
|
|
cmd.proc.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
cmd.Start()
|
|
defer cmd.Stop()
|
|
|
|
cpid, cpgrp := cmd.Info()
|
|
|
|
if cpid == ppid {
|
|
t.Fatalf("Parent and child have the same process ID")
|
|
}
|
|
|
|
if cpgrp == ppgrp {
|
|
t.Fatalf("Parent and child are in the same process group")
|
|
}
|
|
|
|
if cpid != cpgrp {
|
|
t.Fatalf("Child's process group is not the child's process ID")
|
|
}
|
|
}
|
|
|
|
func TestPgid(t *testing.T) {
|
|
ppid, ppgrp := parent()
|
|
|
|
cmd1 := create(t)
|
|
|
|
cmd1.proc.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
cmd1.Start()
|
|
defer cmd1.Stop()
|
|
|
|
cpid1, cpgrp1 := cmd1.Info()
|
|
|
|
if cpid1 == ppid {
|
|
t.Fatalf("Parent and child 1 have the same process ID")
|
|
}
|
|
|
|
if cpgrp1 == ppgrp {
|
|
t.Fatalf("Parent and child 1 are in the same process group")
|
|
}
|
|
|
|
if cpid1 != cpgrp1 {
|
|
t.Fatalf("Child 1's process group is not its process ID")
|
|
}
|
|
|
|
cmd2 := create(t)
|
|
|
|
cmd2.proc.SysProcAttr = &syscall.SysProcAttr{
|
|
Setpgid: true,
|
|
Pgid: cpgrp1,
|
|
}
|
|
cmd2.Start()
|
|
defer cmd2.Stop()
|
|
|
|
cpid2, cpgrp2 := cmd2.Info()
|
|
|
|
if cpid2 == ppid {
|
|
t.Fatalf("Parent and child 2 have the same process ID")
|
|
}
|
|
|
|
if cpgrp2 == ppgrp {
|
|
t.Fatalf("Parent and child 2 are in the same process group")
|
|
}
|
|
|
|
if cpid2 == cpgrp2 {
|
|
t.Fatalf("Child 2's process group is its process ID")
|
|
}
|
|
|
|
if cpid1 == cpid2 {
|
|
t.Fatalf("Child 1 and 2 have the same process ID")
|
|
}
|
|
|
|
if cpgrp1 != cpgrp2 {
|
|
t.Fatalf("Child 1 and 2 are not in the same process group")
|
|
}
|
|
}
|
|
|
|
func TestForeground(t *testing.T) {
|
|
signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU)
|
|
|
|
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
|
|
if err != nil {
|
|
t.Skipf("Can't test Foreground. Couldn't open /dev/tty: %s", err)
|
|
}
|
|
|
|
fpgrp := syscall.Pid_t(0)
|
|
|
|
errno := syscall.Ioctl(tty.Fd(), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&fpgrp)))
|
|
if errno != 0 {
|
|
t.Fatalf("TIOCGPGRP failed with error code: %s", errno)
|
|
}
|
|
|
|
if fpgrp == 0 {
|
|
t.Fatalf("Foreground process group is zero")
|
|
}
|
|
|
|
ppid, ppgrp := parent()
|
|
|
|
cmd := create(t)
|
|
|
|
cmd.proc.SysProcAttr = &syscall.SysProcAttr{
|
|
Ctty: int(tty.Fd()),
|
|
Foreground: true,
|
|
}
|
|
cmd.Start()
|
|
|
|
cpid, cpgrp := cmd.Info()
|
|
|
|
if cpid == ppid {
|
|
t.Fatalf("Parent and child have the same process ID")
|
|
}
|
|
|
|
if cpgrp == ppgrp {
|
|
t.Fatalf("Parent and child are in the same process group")
|
|
}
|
|
|
|
if cpid != cpgrp {
|
|
t.Fatalf("Child's process group is not the child's process ID")
|
|
}
|
|
|
|
cmd.Stop()
|
|
|
|
errno = syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp)))
|
|
if errno != 0 {
|
|
t.Fatalf("TIOCSPGRP failed with error code: %s", errno)
|
|
}
|
|
|
|
signal.Reset()
|
|
}
|