si.ShowWindow = SW_HIDE
}
if sys.ParentProcess != 0 {
- err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, uintptr(unsafe.Pointer(&sys.ParentProcess)), unsafe.Sizeof(sys.ParentProcess), 0, nil)
+ err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, unsafe.Pointer(&sys.ParentProcess), unsafe.Sizeof(sys.ParentProcess), nil, nil)
if err != nil {
return 0, 0, err
}
fd = append(fd, sys.AdditionalInheritedHandles...)
// Do not accidentally inherit more than these handles.
- err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, uintptr(unsafe.Pointer(&fd[0])), uintptr(len(fd))*unsafe.Sizeof(fd[0]), 0, nil)
+ err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fd[0]), uintptr(len(fd))*unsafe.Sizeof(fd[0]), nil, nil)
if err != nil {
return 0, 0, err
}
--- /dev/null
+// Copyright 2021 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.
+
+package syscall
+
+var NewProcThreadAttributeList = newProcThreadAttributeList
+var UpdateProcThreadAttribute = updateProcThreadAttribute
+var DeleteProcThreadAttributeList = deleteProcThreadAttributeList
+
+const PROC_THREAD_ATTRIBUTE_HANDLE_LIST = _PROC_THREAD_ATTRIBUTE_HANDLE_LIST
//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
//sys initializeProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList
//sys deleteProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST) = DeleteProcThreadAttributeList
-//sys updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value uintptr, size uintptr, prevvalue uintptr, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute
+//sys updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute
// syscall interface implementation for other packages
}
return nil, err
}
- al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
+ // size is guaranteed to be ≥1 by initializeProcThreadAttributeList.
+ al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]unsafe.Pointer, (size+ptrSize-1)/ptrSize)[0]))
err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
if err != nil {
return nil, err
import (
"os"
"path/filepath"
+ "runtime"
"syscall"
"testing"
+ "time"
+ "unsafe"
)
func TestWin32finddata(t *testing.T) {
t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", syscall.TOKEN_ALL_ACCESS)
}
}
+
+func TestProcThreadAttributeListPointers(t *testing.T) {
+ list, err := syscall.NewProcThreadAttributeList(1)
+ if err != nil {
+ t.Errorf("unable to create ProcThreadAttributeList: %v", err)
+ }
+ done := make(chan struct{})
+ fds := make([]syscall.Handle, 20)
+ runtime.SetFinalizer(&fds[0], func(*syscall.Handle) {
+ close(done)
+ })
+ err = syscall.UpdateProcThreadAttribute(list, 0, syscall.PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fds[0]), uintptr(len(fds))*unsafe.Sizeof(fds[0]), nil, nil)
+ if err != nil {
+ syscall.DeleteProcThreadAttributeList(list)
+ t.Errorf("unable to update ProcThreadAttributeList: %v", err)
+ return
+ }
+ runtime.GC()
+ runtime.GC()
+ select {
+ case <-done:
+ t.Error("ProcThreadAttributeList was garbage collected unexpectedly")
+ default:
+ }
+ syscall.DeleteProcThreadAttributeList(list)
+ runtime.GC()
+ runtime.GC()
+ select {
+ case <-done:
+ case <-time.After(time.Second):
+ t.Error("ProcThreadAttributeList was not garbage collected after a second")
+ }
+}
package syscall
+import "unsafe"
+
const (
// Windows errors.
ERROR_FILE_NOT_FOUND Errno = 2
}
type _PROC_THREAD_ATTRIBUTE_LIST struct {
- _ [1]byte
+ // This is of type unsafe.Pointer, not of type byte or uintptr, because
+ // the contents of it is mostly a list of pointers, and in most cases,
+ // that's a list of pointers to Go-allocated objects. In order to keep
+ // the GC from collecting these objects, we declare this as unsafe.Pointer.
+ _ [1]unsafe.Pointer
}
const (
return
}
-func updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value uintptr, size uintptr, prevvalue uintptr, returnedsize *uintptr) (err error) {
+func updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) {
r1, _, e1 := Syscall9(procUpdateProcThreadAttribute.Addr(), 7, uintptr(unsafe.Pointer(attrlist)), uintptr(flags), uintptr(attr), uintptr(value), uintptr(size), uintptr(prevvalue), uintptr(unsafe.Pointer(returnedsize)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)