mirror of https://github.com/golang/go.git
syscall: implement syscall.Getppid() on Windows
Also added a test to verify os.Getppid() works across all platforms LGTM=alex.brainman R=golang-codereviews, alex.brainman, shreveal, iant CC=golang-codereviews https://golang.org/cl/102320044
This commit is contained in:
parent
f303b4965c
commit
6f6f1bd054
|
|
@ -1293,6 +1293,32 @@ func TestKillStartProcess(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestGetppid(t *testing.T) {
|
||||
if runtime.GOOS == "nacl" {
|
||||
t.Skip("skipping on nacl")
|
||||
}
|
||||
|
||||
if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
||||
fmt.Print(Getppid())
|
||||
Exit(0)
|
||||
}
|
||||
|
||||
cmd := osexec.Command(Args[0], "-test.run=TestGetppid")
|
||||
cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
|
||||
|
||||
// verify that Getppid() from the forked process reports our process id
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
|
||||
}
|
||||
|
||||
childPpid := string(output)
|
||||
ourPid := fmt.Sprintf("%d", Getpid())
|
||||
if childPpid != ourPid {
|
||||
t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKillFindProcess(t *testing.T) {
|
||||
testKillProcess(t, func(p *Process) {
|
||||
p2, err := FindProcess(p.Pid)
|
||||
|
|
|
|||
|
|
@ -204,6 +204,9 @@ func NewCallbackCDecl(fn interface{}) uintptr
|
|||
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
|
||||
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
|
||||
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
|
||||
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
|
||||
//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
|
||||
//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
|
||||
|
||||
// syscall interface implementation for other packages
|
||||
|
||||
|
|
@ -902,9 +905,37 @@ func FindNextFile(handle Handle, data *Win32finddata) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// TODO(brainman): fix all needed for os
|
||||
func Getppid() (ppid int) { return -1 }
|
||||
func getProcessEntry(pid int) (*ProcessEntry32, error) {
|
||||
snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer CloseHandle(snapshot)
|
||||
var procEntry ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
if err = Process32First(snapshot, &procEntry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if procEntry.ProcessID == uint32(pid) {
|
||||
return &procEntry, nil
|
||||
}
|
||||
err = Process32Next(snapshot, &procEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Getppid() (ppid int) {
|
||||
pe, err := getProcessEntry(Getpid())
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return int(pe.ParentProcessID)
|
||||
}
|
||||
|
||||
// TODO(brainman): fix all needed for os
|
||||
func Fchdir(fd Handle) (err error) { return EWINDOWS }
|
||||
func Link(oldpath, newpath string) (err error) { return EWINDOWS }
|
||||
func Symlink(path, link string) (err error) { return EWINDOWS }
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ var (
|
|||
procGetConsoleMode = modkernel32.NewProc("GetConsoleMode")
|
||||
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
|
||||
procReadConsoleW = modkernel32.NewProc("ReadConsoleW")
|
||||
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procProcess32FirstW = modkernel32.NewProc("Process32FirstW")
|
||||
procProcess32NextW = modkernel32.NewProc("Process32NextW")
|
||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
||||
|
|
@ -1254,6 +1257,43 @@ func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, input
|
|||
return
|
||||
}
|
||||
|
||||
func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) {
|
||||
r0, _, e1 := Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0)
|
||||
handle = Handle(r0)
|
||||
if handle == InvalidHandle {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
|
||||
r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
|
||||
if r0 != 0 {
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ var (
|
|||
procGetConsoleMode = modkernel32.NewProc("GetConsoleMode")
|
||||
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
|
||||
procReadConsoleW = modkernel32.NewProc("ReadConsoleW")
|
||||
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procProcess32FirstW = modkernel32.NewProc("Process32FirstW")
|
||||
procProcess32NextW = modkernel32.NewProc("Process32NextW")
|
||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
||||
|
|
@ -1254,6 +1257,43 @@ func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, input
|
|||
return
|
||||
}
|
||||
|
||||
func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) {
|
||||
r0, _, e1 := Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0)
|
||||
handle = Handle(r0)
|
||||
if handle == InvalidHandle {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) {
|
||||
r1, _, e1 := Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
|
||||
r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
|
||||
if r0 != 0 {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,17 @@ const (
|
|||
CTRL_BREAK_EVENT = 1
|
||||
)
|
||||
|
||||
const (
|
||||
// flags for CreateToolhelp32Snapshot
|
||||
TH32CS_SNAPHEAPLIST = 0x01
|
||||
TH32CS_SNAPPROCESS = 0x02
|
||||
TH32CS_SNAPTHREAD = 0x04
|
||||
TH32CS_SNAPMODULE = 0x08
|
||||
TH32CS_SNAPMODULE32 = 0x10
|
||||
TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPMODULE | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD
|
||||
TH32CS_INHERIT = 0x80000000
|
||||
)
|
||||
|
||||
const (
|
||||
// do not reorder
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME = 1 << iota
|
||||
|
|
@ -462,6 +473,19 @@ type ProcessInformation struct {
|
|||
ThreadId uint32
|
||||
}
|
||||
|
||||
type ProcessEntry32 struct {
|
||||
Size uint32
|
||||
Usage uint32
|
||||
ProcessID uint32
|
||||
DefaultHeapID uintptr
|
||||
ModuleID uint32
|
||||
Threads uint32
|
||||
ParentProcessID uint32
|
||||
PriClassBase int32
|
||||
Flags uint32
|
||||
ExeFile [MAX_PATH]uint16
|
||||
}
|
||||
|
||||
type Systemtime struct {
|
||||
Year uint16
|
||||
Month uint16
|
||||
|
|
|
|||
Loading…
Reference in New Issue