mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
internal/poll: don't call Seek for overlapped Windows handles
Overlapped handles don't have the file pointer updated when performing I/O operations, so there is no need to call FD.Seek to reset the file pointer. Also, some overlapped file handles don't support seeking. See #74951. Fixes #74951. Change-Id: I0edd53beed7d3862730f3b2ed5fe9ba490e66c06 Reviewed-on: https://go-review.googlesource.com/c/go/+/697295 Reviewed-by: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
853fc12739
commit
509d5f647f
2 changed files with 58 additions and 10 deletions
|
|
@ -622,12 +622,22 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) {
|
||||||
|
|
||||||
fd.l.Lock()
|
fd.l.Lock()
|
||||||
defer fd.l.Unlock()
|
defer fd.l.Unlock()
|
||||||
|
if fd.isBlocking {
|
||||||
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
|
defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
|
||||||
defer fd.setOffset(curoffset)
|
defer fd.setOffset(curoffset)
|
||||||
|
} else {
|
||||||
|
// Overlapped handles don't have the file pointer updated
|
||||||
|
// when performing I/O operations, so there is no need to
|
||||||
|
// call Seek to reset the file pointer.
|
||||||
|
// Also, some overlapped file handles don't support seeking.
|
||||||
|
// See https://go.dev/issues/74951.
|
||||||
|
curoffset := fd.offset
|
||||||
|
defer fd.setOffset(curoffset)
|
||||||
|
}
|
||||||
o := &fd.rop
|
o := &fd.rop
|
||||||
o.InitBuf(b)
|
o.InitBuf(b)
|
||||||
fd.setOffset(off)
|
fd.setOffset(off)
|
||||||
|
|
@ -847,12 +857,22 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
|
||||||
|
|
||||||
fd.l.Lock()
|
fd.l.Lock()
|
||||||
defer fd.l.Unlock()
|
defer fd.l.Unlock()
|
||||||
|
if fd.isBlocking {
|
||||||
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
|
defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
|
||||||
defer fd.setOffset(curoffset)
|
defer fd.setOffset(curoffset)
|
||||||
|
} else {
|
||||||
|
// Overlapped handles don't have the file pointer updated
|
||||||
|
// when performing I/O operations, so there is no need to
|
||||||
|
// call Seek to reset the file pointer.
|
||||||
|
// Also, some overlapped file handles don't support seeking.
|
||||||
|
// See https://go.dev/issues/74951.
|
||||||
|
curoffset := fd.offset
|
||||||
|
defer fd.setOffset(curoffset)
|
||||||
|
}
|
||||||
|
|
||||||
var ntotal int
|
var ntotal int
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -1883,6 +1883,34 @@ func TestFileOverlappedSeek(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileOverlappedReadAtVolume(t *testing.T) {
|
||||||
|
// Test that we can use File.ReadAt with an overlapped volume handle.
|
||||||
|
// See https://go.dev/issues/74951.
|
||||||
|
t.Parallel()
|
||||||
|
name := `\\.\` + filepath.VolumeName(t.TempDir())
|
||||||
|
namep, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
h, err := syscall.CreateFile(namep,
|
||||||
|
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
|
||||||
|
syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_READ,
|
||||||
|
nil, syscall.OPEN_ALWAYS, syscall.FILE_FLAG_OVERLAPPED, 0)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, syscall.ERROR_ACCESS_DENIED) {
|
||||||
|
t.Skip("skipping test: access denied")
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f := os.NewFile(uintptr(h), name)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var buf [0]byte
|
||||||
|
if _, err := f.ReadAt(buf[:], 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPipe(t *testing.T) {
|
func TestPipe(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue