mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-27 20:36:31 -04:00
windows: use Go-managed pointer list for ProcThreadAttributeList
It turns out that if you write Go pointers to Go memory, the Go compiler must be involved so that it generates various calls to the GC in the process. Letting Windows write Go pointers to Go memory violated this. We fix this by having all the Windows-managed memory be just a boring []byte blob. Then, in order to prevent the GC from prematurely cleaning up the pointers referenced by that []byte blob, or in the future moving memory and attempting to fix up pointers, we copy the data to the Windows heap and then maintain a little array of pointers that have been used. Every time the Update function is called with a new pointer, we make a copy and append it to the list. Then, on Delete, we free the pointers from the Windows heap. Updates golang/go#44900. Change-Id: I42340a93fd9f6b8d10340634cf833fd4559a5f4f Reviewed-on: https://go-review.googlesource.com/c/sys/+/300369 Trust: Jason A. Donenfeld <Jason@zx2c4.com> Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
@@ -18,7 +18,6 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@@ -506,39 +505,6 @@ func TestNTStatusConversion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcThreadAttributeListPointers(t *testing.T) {
|
||||
list, err := windows.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 = list.Update(windows.PROC_THREAD_ATTRIBUTE_HANDLE_LIST, 0, unsafe.Pointer(&fds[0]), uintptr(len(fds))*unsafe.Sizeof(fds[0]), nil, nil)
|
||||
if err != nil {
|
||||
list.Delete()
|
||||
t.Errorf("unable to update ProcThreadAttributeList: %v", err)
|
||||
return
|
||||
}
|
||||
runtime.GC()
|
||||
runtime.GC()
|
||||
select {
|
||||
case <-done:
|
||||
t.Error("ProcThreadAttributeList was garbage collected unexpectedly")
|
||||
default:
|
||||
}
|
||||
list.Delete()
|
||||
runtime.GC()
|
||||
runtime.GC()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
t.Error("ProcThreadAttributeList was not garbage collected after a second")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPEBFilePath(t *testing.T) {
|
||||
peb := windows.RtlGetCurrentPeb()
|
||||
if peb == nil || peb.Ldr == nil {
|
||||
|
||||
Reference in New Issue
Block a user