Created
September 2, 2019 20:22
-
-
Save smira/9dbb8e1f7877510014bcc6217af9e68a to your computer and use it in GitHub Desktop.
waitid implementation for Go linux/amd64
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package linux | |
import ( | |
"fmt" | |
"syscall" | |
"unsafe" | |
) | |
// Values for waitid() idtype parameter | |
// | |
//nolint: golint | |
const ( | |
P_ALL = 0 | |
P_PID = 1 | |
P_PGID = 2 | |
) | |
// SiginfoWaitid provides version of siginfo_t struct for waitid() syscall | |
type SiginfoWaitid struct { | |
Signo int32 | |
Errno int32 | |
Code int32 | |
_ int32 // padding | |
Pid uint32 | |
UID uint32 | |
Status int32 | |
_ [100]byte // struct should be 128 bytes | |
} | |
// Waitid implements Linux-specific syscall waitid() | |
func Waitid(idtype int, id int, infop *SiginfoWaitid, options int) error { | |
_, _, e := syscall.Syscall6(syscall.SYS_WAITID, uintptr(idtype), uintptr(id), uintptr(unsafe.Pointer(infop)), uintptr(options), 0, 0) | |
if e == 0 { | |
return nil | |
} | |
return e | |
} | |
func init() { | |
if unsafe.Sizeof(SiginfoWaitid{}) != 128 { | |
panic(fmt.Sprintf("SiginfoWaitid structure should be 128 bytes, but it is %d bytes", unsafe.Sizeof(SiginfoWaitid{}))) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package linux_test | |
import ( | |
"os/exec" | |
"syscall" | |
"testing" | |
"github.com/stretchr/testify/suite" | |
"./linux" | |
) | |
type WaitidSuite struct { | |
suite.Suite | |
} | |
func (suite *WaitidSuite) TestWaitidNoProcesses() { | |
var info linux.SiginfoWaitid | |
err := linux.Waitid(linux.P_ALL, 0, &info, syscall.WEXITED|syscall.WNOHANG) | |
suite.Assert().Equal(err, syscall.ECHILD) | |
} | |
func (suite *WaitidSuite) TestWaitidSingleProcess() { | |
var info linux.SiginfoWaitid | |
cmd := exec.Command("/bin/sh", "-c", ":") | |
suite.Assert().NoError(cmd.Start()) | |
err := linux.Waitid(linux.P_ALL, 0, &info, syscall.WEXITED|syscall.WNOWAIT) | |
suite.Assert().Nil(err) | |
// zombie status retrieved, but zombie is not reaped | |
suite.Assert().EqualValues(info.Pid, cmd.Process.Pid) | |
// cmd.Wait should still get zombie status | |
suite.Assert().Nil(cmd.Wait()) | |
} | |
func TestWaitidSuite(t *testing.T) { | |
suite.Run(t, new(WaitidSuite)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment