Skip to content

Commit

Permalink
Added runtime.KeepAlive for the new stricter 1.8 GC
Browse files Browse the repository at this point in the history
Signed-off-by: Darren Stahl <darst@microsoft.com>
  • Loading branch information
darstahl committed May 2, 2017
1 parent f3b1913 commit bb53aa8
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 36 deletions.
6 changes: 4 additions & 2 deletions backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ type BackupFileReader struct {
// Read will attempt to read the security descriptor of the file.
func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
r := &BackupFileReader{f, includeSecurity, 0}
runtime.SetFinalizer(r, func(r *BackupFileReader) { r.Close() })
return r
}

Expand All @@ -196,6 +195,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
if err != nil {
return 0, &os.PathError{"BackupRead", r.f.Name(), err}
}
runtime.KeepAlive(r.f)
if bytesRead == 0 {
return 0, io.EOF
}
Expand All @@ -207,6 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
func (r *BackupFileReader) Close() error {
if r.ctx != 0 {
backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
runtime.KeepAlive(r.f)
r.ctx = 0
}
return nil
Expand All @@ -223,7 +224,6 @@ type BackupFileWriter struct {
// Write() will attempt to restore the security descriptor from the stream.
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
w := &BackupFileWriter{f, includeSecurity, 0}
runtime.SetFinalizer(w, func(w *BackupFileWriter) { w.Close() })
return w
}

Expand All @@ -234,6 +234,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
if err != nil {
return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
}
runtime.KeepAlive(w.f)
if int(bytesWritten) != len(b) {
return int(bytesWritten), errors.New("not all bytes could be written")
}
Expand All @@ -245,6 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
func (w *BackupFileWriter) Close() error {
if w.ctx != 0 {
backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
runtime.KeepAlive(w.f)
w.ctx = 0
}
return nil
Expand Down
16 changes: 12 additions & 4 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ func makeWin32File(h syscall.Handle) (*win32File, error) {
if err != nil {
return nil, err
}
runtime.SetFinalizer(f, (*win32File).closeHandle)
return f, nil
}

Expand All @@ -103,7 +102,6 @@ func (f *win32File) closeHandle() {
// Close closes a win32File.
func (f *win32File) Close() error {
f.closeHandle()
runtime.SetFinalizer(f, nil)
return nil
}

Expand Down Expand Up @@ -166,6 +164,12 @@ func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, er
if wait {
r = <-c.ch
}

// runtime.KeepAlive is needed, as c is passed via native
// code to ioCompletionProcessor, c must remain alive
// until the channel read is complete.
runtime.KeepAlive(c)

err = r.err
if err == syscall.ERROR_OPERATION_ABORTED {
if f.closing {
Expand All @@ -188,6 +192,7 @@ func (f *win32File) Read(b []byte) (int, error) {
var bytes uint32
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
n, err := f.asyncIo(c, f.readDeadline, bytes, err)
runtime.KeepAlive(b)

// Handle EOF conditions.
if err == nil && n == 0 && len(b) != 0 {
Expand All @@ -207,7 +212,9 @@ func (f *win32File) Write(b []byte) (int, error) {
}
var bytes uint32
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
return f.asyncIo(c, f.writeDeadline, bytes, err)
n, err := f.asyncIo(c, f.writeDeadline, bytes, err)
runtime.KeepAlive(b)
return n, err
}

func (f *win32File) SetReadDeadline(t time.Time) error {
Expand All @@ -221,5 +228,6 @@ func (f *win32File) SetWriteDeadline(t time.Time) error {
}

func (f *win32File) Flush() error {
return syscall.FlushFileBuffers(f.handle)
err := syscall.FlushFileBuffers(f.handle)
return err
}
4 changes: 4 additions & 0 deletions fileinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package winio

import (
"os"
"runtime"
"syscall"
"unsafe"
)
Expand All @@ -28,6 +29,7 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return bi, nil
}

Expand All @@ -36,6 +38,7 @@ func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return nil
}

Expand All @@ -52,5 +55,6 @@ func GetFileID(f *os.File) (*FileIDInfo, error) {
if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return fileID, nil
}
14 changes: 9 additions & 5 deletions pipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

package winio

// #include <stdlib.h>
import "C"

import (
"errors"
"io"
Expand All @@ -21,7 +24,7 @@ import (

type securityAttributes struct {
Length uint32
SecurityDescriptor *byte
SecurityDescriptor unsafe.Pointer
InheritHandle uint32
}

Expand Down Expand Up @@ -231,12 +234,13 @@ func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig,
mode |= cPIPE_TYPE_MESSAGE
}

var sa securityAttributes
sa.Length = uint32(unsafe.Sizeof(sa))
sa := &securityAttributes{}
sa.Length = uint32(unsafe.Sizeof(*sa))
if securityDescriptor != nil {
sa.SecurityDescriptor = &securityDescriptor[0]
sa.SecurityDescriptor = C.CBytes(securityDescriptor)
defer C.free(sa.SecurityDescriptor)
}
h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, &sa)
h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa)
if err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
Expand Down
Loading

0 comments on commit bb53aa8

Please sign in to comment.