]> Cypherpunks repositories - gostls13.git/commitdiff
windows: syscall: Make ForkExec acquire the ForkLock
authorHector Chu <hectorchu@gmail.com>
Thu, 3 Feb 2011 01:50:41 +0000 (12:50 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Thu, 3 Feb 2011 01:50:41 +0000 (12:50 +1100)
so that spawned processes avoid inheriting pipes.

Implement CloseOnExec.
Make file and pipe handles inheritable.

R=rsc, brainman, vincent.vanackere
CC=golang-dev
https://golang.org/cl/4126047

src/pkg/syscall/exec_windows.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go
src/pkg/syscall/ztypes_windows_386.go

index c3ed3ba98eceda78f4897747de1c036fa58bdeeb..64a0030dc6b5da4a7b08b113187692398ca9047b 100644 (file)
@@ -107,7 +107,7 @@ func escapeAddQuotes(s string) string {
 
 
 func CloseOnExec(fd int) {
-       return
+       SetHandleInformation(int32(fd), HANDLE_FLAG_INHERIT, 0)
 }
 
 func SetNonblock(fd int, nonblocking bool) (errno int) {
@@ -144,6 +144,12 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
        startupInfo.StdOutput = 0
        startupInfo.StdErr = 0
 
+       // Acquire the fork lock so that no other threads
+       // create new fds that are not yet close-on-exec
+       // before we fork.
+       ForkLock.Lock()
+       defer ForkLock.Unlock()
+
        var currentProc, _ = GetCurrentProcess()
        if len(fd) > 0 && fd[0] > 0 {
                if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
index 762ed53db66da652061f93e905984aa6c70ac267..267b30647fbe882fc033937e2d4c7a75e5fd73bb 100644 (file)
@@ -111,7 +111,7 @@ func NewCallback(fn interface{}) uintptr
 //sys  GetVersion() (ver uint32, errno int)
 //sys  FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) = FormatMessageW
 //sys  ExitProcess(exitcode uint32)
-//sys  CreateFile(name *uint16, access uint32, mode uint32, sa *byte, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) [failretval==-1] = CreateFileW
+//sys  CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) [failretval==-1] = CreateFileW
 //sys  ReadFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int)
 //sys  WriteFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int)
 //sys  SetFilePointer(handle int32, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) [failretval==0xffffffff]
@@ -123,7 +123,7 @@ func NewCallback(fn interface{}) uintptr
 //sys  GetFileInformationByHandle(handle int32, data *ByHandleFileInformation) (ok bool, errno int)
 //sys  GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) = GetCurrentDirectoryW
 //sys  SetCurrentDirectory(path *uint16) (ok bool, errno int) = SetCurrentDirectoryW
-//sys  CreateDirectory(path *uint16, sa *byte) (ok bool, errno int) = CreateDirectoryW
+//sys  CreateDirectory(path *uint16, sa *SecurityAttributes) (ok bool, errno int) = CreateDirectoryW
 //sys  RemoveDirectory(path *uint16) (ok bool, errno int) = RemoveDirectoryW
 //sys  DeleteFile(path *uint16) (ok bool, errno int) = DeleteFileW
 //sys  MoveFile(from *uint16, to *uint16) (ok bool, errno int) = MoveFileW
@@ -141,7 +141,7 @@ func NewCallback(fn interface{}) uintptr
 //sys  DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int)
 //sys  WaitForSingleObject(handle int32, waitMilliseconds uint32) (event uint32, errno int) [failretval==0xffffffff]
 //sys  GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW
-//sys  CreatePipe(readhandle *uint32, writehandle *uint32, lpsa *byte, size uint32) (ok bool, errno int)
+//sys  CreatePipe(readhandle *uint32, writehandle *uint32, sa *SecurityAttributes, size uint32) (ok bool, errno int)
 //sys  GetFileType(filehandle uint32) (n uint32, errno int)
 //sys  CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
 //sys  CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
@@ -157,6 +157,7 @@ func NewCallback(fn interface{}) uintptr
 //sys  GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
 //sys  CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW
 //sys  LocalFree(hmem uint32) (handle uint32, errno int) [failretval!=0]
+//sys  SetHandleInformation(handle int32, mask uint32, flags uint32) (ok bool, errno int)
 
 // syscall interface implementation for other packages
 
@@ -181,6 +182,13 @@ func Errstr(errno int) string {
 
 func Exit(code int) { ExitProcess(uint32(code)) }
 
+func makeInheritSa() *SecurityAttributes {
+       var sa SecurityAttributes
+       sa.Length = uint32(unsafe.Sizeof(sa))
+       sa.InheritHandle = 1
+       return &sa
+}
+
 func Open(path string, mode int, perm uint32) (fd int, errno int) {
        if len(path) == 0 {
                return -1, ERROR_FILE_NOT_FOUND
@@ -202,6 +210,10 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
                access |= FILE_APPEND_DATA
        }
        sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
+       var sa *SecurityAttributes
+       if mode&O_CLOEXEC == 0 {
+               sa = makeInheritSa()
+       }
        var createmode uint32
        switch {
        case mode&O_CREAT != 0:
@@ -215,7 +227,7 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
        default:
                createmode = OPEN_EXISTING
        }
-       h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, nil, createmode, FILE_ATTRIBUTE_NORMAL, 0)
+       h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
        return int(h), int(e)
 }
 
@@ -439,7 +451,7 @@ func Pipe(p []int) (errno int) {
                return EINVAL
        }
        var r, w uint32
-       if ok, errno := CreatePipe(&r, &w, nil, 0); !ok {
+       if ok, errno := CreatePipe(&r, &w, makeInheritSa(), 0); !ok {
                return errno
        }
        p[0] = int(r)
index b71177e428774a7c929700a62f24c6e0f3318040..d5f170fe39abb29d98e93afe87e3f8c500f086b1 100644 (file)
@@ -66,6 +66,7 @@ var (
        procGetCommandLineW            = getSysProcAddr(modkernel32, "GetCommandLineW")
        procCommandLineToArgvW         = getSysProcAddr(modshell32, "CommandLineToArgvW")
        procLocalFree                  = getSysProcAddr(modkernel32, "LocalFree")
+       procSetHandleInformation       = getSysProcAddr(modkernel32, "SetHandleInformation")
        procWSAStartup                 = getSysProcAddr(modwsock32, "WSAStartup")
        procWSACleanup                 = getSysProcAddr(modwsock32, "WSACleanup")
        procsocket                     = getSysProcAddr(modwsock32, "socket")
@@ -180,7 +181,7 @@ func ExitProcess(exitcode uint32) {
        return
 }
 
-func CreateFile(name *uint16, access uint32, mode uint32, sa *byte, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) {
+func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) {
        r0, _, e1 := Syscall9(procCreateFileW, 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
        handle = int32(r0)
        if handle == -1 {
@@ -368,7 +369,7 @@ func SetCurrentDirectory(path *uint16) (ok bool, errno int) {
        return
 }
 
-func CreateDirectory(path *uint16, sa *byte) (ok bool, errno int) {
+func CreateDirectory(path *uint16, sa *SecurityAttributes) (ok bool, errno int) {
        r0, _, e1 := Syscall(procCreateDirectoryW, 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
        ok = bool(r0 != 0)
        if !ok {
@@ -630,8 +631,8 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) {
        return
 }
 
-func CreatePipe(readhandle *uint32, writehandle *uint32, lpsa *byte, size uint32) (ok bool, errno int) {
-       r0, _, e1 := Syscall6(procCreatePipe, 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(lpsa)), uintptr(size), 0, 0)
+func CreatePipe(readhandle *uint32, writehandle *uint32, sa *SecurityAttributes, size uint32) (ok bool, errno int) {
+       r0, _, e1 := Syscall6(procCreatePipe, 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0)
        ok = bool(r0 != 0)
        if !ok {
                if e1 != 0 {
@@ -861,6 +862,21 @@ func LocalFree(hmem uint32) (handle uint32, errno int) {
        return
 }
 
+func SetHandleInformation(handle int32, mask uint32, flags uint32) (ok bool, errno int) {
+       r0, _, e1 := Syscall(procSetHandleInformation, 3, uintptr(handle), uintptr(mask), uintptr(flags))
+       ok = bool(r0 != 0)
+       if !ok {
+               if e1 != 0 {
+                       errno = int(e1)
+               } else {
+                       errno = EINVAL
+               }
+       } else {
+               errno = 0
+       }
+       return
+}
+
 func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
        r0, _, _ := Syscall(procWSAStartup, 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
        sockerrno = int(r0)
index b1271aff178306a24ed64109c4ed12d3b79cb935..e9ab354619373d814c92ca1a744fcef69900ec73 100644 (file)
@@ -74,6 +74,7 @@ const (
        OPEN_ALWAYS       = 4
        TRUNCATE_EXISTING = 5
 
+       HANDLE_FLAG_INHERIT    = 0x00000001
        STARTF_USESTDHANDLES   = 0x00000100
        DUPLICATE_CLOSE_SOURCE = 0x00000001
        DUPLICATE_SAME_ACCESS  = 0x00000002
@@ -172,6 +173,12 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
        return
 }
 
+type SecurityAttributes struct {
+       Length             uint32
+       SecurityDescriptor uintptr
+       InheritHandle      uint32
+}
+
 type Overlapped struct {
        Internal     uint32
        InternalHigh uint32