Guidelines for contributing os.Getppid() on Windows

315 views
Skip to first unread message

Alan Shreve

unread,
Apr 26, 2014, 6:25:47 PM4/26/14
to golan...@googlegroups.com
Just recently I needed a function which would pull out the parent process information on Windows. While implementing this, I noticed that there is no implementation for os.Getppid() on windows so I thought I’d contribute my implementation. Before I wrote it up, I just wanted to verify a few things:

I should define the new syscalls by writing comments in syscall/syscall_windows.go and then run the mksyscall_windows.pl script to generate the functions

I should define any new Win32 API types and/or constants in ztypes_windows.go

The implementation for getting the parent process identifier on windows is not a completely trivial exercise. I’m not entirely certain how to go about testing this functionality. How do you test your use of the Win32 API? It doesn’t look like there are any tests around getppid on any platforms.

- alan

minux

unread,
Apr 26, 2014, 6:40:58 PM4/26/14
to Alan Shreve, golang-dev
Hi Alan,

If this is your first contribution to Go, please read golang.org/doc/contribute.html for
the process.

On Sat, Apr 26, 2014 at 6:25 PM, Alan Shreve <al...@inconshreveable.com> wrote:
Just recently I needed a function which would pull out the parent process information on Windows. While implementing this, I noticed that there is no implementation for os.Getppid() on windows so I thought I'd contribute my implementation. Before I wrote it up, I just wanted to verify a few things:

I should define the new syscalls by writing comments in syscall/syscall_windows.go and then run the mksyscall_windows.pl script to generate the functions
yes.

I should define any new Win32 API types and/or constants in ztypes_windows.go
yes.

The implementation for getting the parent process identifier on windows is not a completely trivial exercise. I'm not entirely certain how to go about testing this functionality. How do you test your use of the Win32 API? It doesn't look like there are any tests around getppid on any platforms.
use os/exec to execute a child process, and relay the result of os.Getppid back to its parent
though pipes. you can write a generic test in os for os.Getppid for every platform.
(there are tests that do this in the tree, e.g. pkg/os/exec/exec_test.go)

One last thing to bear in mind is that the tree is currently frozen for 1.3 release, so please
send your CL after Go 1.3 is released, thank you.
(you can view more about the Go release schedule here: golang.org/s/releasesched)

Alan Shreve

unread,
Apr 26, 2014, 6:45:55 PM4/26/14
to minux, golang-dev
Awesome, thank you for the pointer to the exec test, that’ll be quite helpful.

- alan

brainman

unread,
Apr 26, 2014, 8:36:29 PM4/26/14
to golan...@googlegroups.com, al...@inconshreveable.com
You should add all windows struct and const into ztypes_windows.go and function prototypes to syscall_windows.go, then run:

cd $GOROOT/src/pkg/syscall
GOOS=windows GOARCH=386 ./mkall.sh
GOOS=windows GOARCH=amd64 ./mkall.sh

on unix or

cd %GOROOT%\src\pkg\syscall
mkall_windows.bat 386
mkall_windows.bat amd64

on windows (unchecked, I don't have computer now). These scripts will update zsyscall_windows_386.go and zsyscall_windows_amd64.go files, then you can use new Windows APIs from outside of syscall package.

Alex

Alan Shreve

unread,
Apr 27, 2014, 11:33:23 PM4/27/14
to brainman, golan...@googlegroups.com
I got this all working and added a test to verify Getppid() across all platform with your suggestion to reuse the child process technique used by os/exec’s tests. I’ll hold off on submitting the CL until after 1.3 ships per minux’s request.

I just ended up with one question about the implementation:

The code requires mapping the ProcessEntry32 structure: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx

Most of the fields in the structure are easy to map because they have explicit sizes. DefaultHeapId, however, is a ULONG_PTR which is 32-bit or 64-bit depending on the architecture. Can I map this as a uintptr and be guaranteed it will be of the proper size, or should I create two separate definitions in ztypes_windows_386.go/ztypes_windows_amd64.go?

- alan

--

---
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

minux

unread,
Apr 27, 2014, 11:48:20 PM4/27/14
to Alan Shreve, brainman, golang-dev
On Sun, Apr 27, 2014 at 11:33 PM, Alan Shreve <al...@inconshreveable.com> wrote:
I got this all working and added a test to verify Getppid() across all platform with your suggestion to reuse the child process technique used by os/exec’s tests. I’ll hold off on submitting the CL until after 1.3 ships per minux’s request.

I just ended up with one question about the implementation:

The code requires mapping the ProcessEntry32 structure: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx

Most of the fields in the structure are easy to map because they have explicit sizes. DefaultHeapId, however, is a ULONG_PTR which is 32-bit or 64-bit depending on the architecture. Can I map this as a uintptr and be guaranteed it will be of the proper size, or should I create two separate definitions in ztypes_windows_386.go/ztypes_windows_amd64.go?
I think having just one definition helps to ease future maintenance.
however, if that field could contain genuine pointers, you'd better use unsafe.Pointer instead of uintptr,
because otherwise the precise GC will miss the pointer and collect the object it points to.

Alan Shreve

unread,
Apr 27, 2014, 11:58:18 PM4/27/14
to minux, brainman, golang-dev
Okay I prefer that as well as long as the size of uintptr is guaranteed to be 32bit/64bit as appropriate.

The memory in question is allocated/freed by calls to the win32 API. As far as I understand, Go’s GC shouldn’t need to know about it.

minux

unread,
Apr 28, 2014, 12:00:24 AM4/28/14
to Alan Shreve, brainman, golang-dev
On Sun, Apr 27, 2014 at 11:58 PM, Alan Shreve <al...@inconshreveable.com> wrote:
Okay I prefer that as well as long as the size of uintptr is guaranteed to be 32bit/64bit as appropriate.

The memory in question is allocated/freed by calls to the win32 API. As far as I understand, Go’s GC shouldn’t need to know about it.
Alright, if it doesn't point to Go heap, then uintptr is perfectly fine.
(you might want to comment about this so that reviewers don't need to look it up.)

jjef...@sp.com.au

unread,
Jun 29, 2014, 6:01:40 AM6/29/14
to golan...@googlegroups.com, al...@inconshreveable.com
I've just come across this post, I know it's pretty old. I just thought I might mention that although this implementation is about as good an implementation you can get of Getppid on Windows, it does have a signficant difference in behaviour to the Un*x implementations. This function will return the parent's PID even after the parent has terminated, in contrast to the Un*x implementations, which all return 1 if the original parent process has terminated.

To make things worse, Windows likes to re-use PIDs quite quickly, so on Windows Getppid could return the PID of a running process which did not start the process.

AFAIK, there is no way around this on Windows, so os.Getppid() would need to be used with extreme caution on Windows. The longer the process has been running, the higher the possibility of it returning a misleading result.
Reply all
Reply to author
Forward
0 new messages