Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
b1deb3be
Commit
b1deb3be
authored
Apr 26, 2011
by
Alex Brainman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
os: fix race in ReadAt/WriteAt on Windows
R=bradfitzgo, rsc, peterGo CC=golang-dev
https://golang.org/cl/4441051
parent
2d99974e
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
147 additions
and
46 deletions
+147
-46
file.go
src/pkg/os/file.go
+10
-8
file_plan9.go
src/pkg/os/file_plan9.go
+33
-0
file_unix.go
src/pkg/os/file_unix.go
+33
-0
file_windows.go
src/pkg/os/file_windows.go
+71
-0
syscall_windows.go
src/pkg/syscall/syscall_windows.go
+0
-38
No files found.
src/pkg/os/file.go
View file @
b1deb3be
...
@@ -8,6 +8,7 @@ package os
...
@@ -8,6 +8,7 @@ package os
import
(
import
(
"runtime"
"runtime"
"sync"
"syscall"
"syscall"
)
)
...
@@ -15,8 +16,9 @@ import (
...
@@ -15,8 +16,9 @@ import (
type
File
struct
{
type
File
struct
{
fd
int
fd
int
name
string
name
string
dirinfo
*
dirInfo
// nil unless directory being read
dirinfo
*
dirInfo
// nil unless directory being read
nepipe
int
// number of consecutive EPIPE in Write
nepipe
int
// number of consecutive EPIPE in Write
l
sync
.
Mutex
// used to implement windows pread/pwrite
}
}
// Fd returns the integer Unix file descriptor referencing the open file.
// Fd returns the integer Unix file descriptor referencing the open file.
...
@@ -30,7 +32,7 @@ func NewFile(fd int, name string) *File {
...
@@ -30,7 +32,7 @@ func NewFile(fd int, name string) *File {
if
fd
<
0
{
if
fd
<
0
{
return
nil
return
nil
}
}
f
:=
&
File
{
fd
,
name
,
nil
,
0
}
f
:=
&
File
{
fd
:
fd
,
name
:
name
}
runtime
.
SetFinalizer
(
f
,
(
*
File
)
.
Close
)
runtime
.
SetFinalizer
(
f
,
(
*
File
)
.
Close
)
return
f
return
f
}
}
...
@@ -85,7 +87,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
...
@@ -85,7 +87,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
if
file
==
nil
{
if
file
==
nil
{
return
0
,
EINVAL
return
0
,
EINVAL
}
}
n
,
e
:=
syscall
.
Read
(
file
.
fd
,
b
)
n
,
e
:=
file
.
read
(
b
)
if
n
<
0
{
if
n
<
0
{
n
=
0
n
=
0
}
}
...
@@ -107,7 +109,7 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
...
@@ -107,7 +109,7 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
return
0
,
EINVAL
return
0
,
EINVAL
}
}
for
len
(
b
)
>
0
{
for
len
(
b
)
>
0
{
m
,
e
:=
syscall
.
Pread
(
file
.
fd
,
b
,
off
)
m
,
e
:=
file
.
pread
(
b
,
off
)
if
m
==
0
&&
!
iserror
(
e
)
{
if
m
==
0
&&
!
iserror
(
e
)
{
return
n
,
EOF
return
n
,
EOF
}
}
...
@@ -129,7 +131,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
...
@@ -129,7 +131,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
if
file
==
nil
{
if
file
==
nil
{
return
0
,
EINVAL
return
0
,
EINVAL
}
}
n
,
e
:=
syscall
.
Write
(
file
.
fd
,
b
)
n
,
e
:=
file
.
write
(
b
)
if
n
<
0
{
if
n
<
0
{
n
=
0
n
=
0
}
}
...
@@ -150,7 +152,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
...
@@ -150,7 +152,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
return
0
,
EINVAL
return
0
,
EINVAL
}
}
for
len
(
b
)
>
0
{
for
len
(
b
)
>
0
{
m
,
e
:=
syscall
.
Pwrite
(
file
.
fd
,
b
,
off
)
m
,
e
:=
file
.
pwrite
(
b
,
off
)
if
iserror
(
e
)
{
if
iserror
(
e
)
{
err
=
&
PathError
{
"write"
,
file
.
name
,
Errno
(
e
)}
err
=
&
PathError
{
"write"
,
file
.
name
,
Errno
(
e
)}
break
break
...
@@ -167,7 +169,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
...
@@ -167,7 +169,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
// relative to the current offset, and 2 means relative to the end.
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an Error, if any.
// It returns the new offset and an Error, if any.
func
(
file
*
File
)
Seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
Error
)
{
func
(
file
*
File
)
Seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
Error
)
{
r
,
e
:=
syscall
.
Seek
(
file
.
fd
,
offset
,
whence
)
r
,
e
:=
file
.
seek
(
offset
,
whence
)
if
!
iserror
(
e
)
&&
file
.
dirinfo
!=
nil
&&
r
!=
0
{
if
!
iserror
(
e
)
&&
file
.
dirinfo
!=
nil
&&
r
!=
0
{
e
=
syscall
.
EISDIR
e
=
syscall
.
EISDIR
}
}
...
...
src/pkg/os/file_plan9.go
View file @
b1deb3be
...
@@ -117,6 +117,39 @@ func (f *File) Sync() (err Error) {
...
@@ -117,6 +117,39 @@ func (f *File) Sync() (err Error) {
return
nil
return
nil
}
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to nil.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Pread
(
f
.
fd
,
b
,
off
)
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
syscall
.
Error
)
{
return
syscall
.
Pwrite
(
f
.
fd
,
b
,
off
)
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
syscall
.
Error
)
{
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/os/file_unix.go
View file @
b1deb3be
...
@@ -96,6 +96,39 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
...
@@ -96,6 +96,39 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
return
return
}
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
int
)
{
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
return
syscall
.
Pread
(
f
.
fd
,
b
,
off
)
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
int
)
{
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
return
syscall
.
Pwrite
(
f
.
fd
,
b
,
off
)
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
int
)
{
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/os/file_windows.go
View file @
b1deb3be
...
@@ -165,6 +165,77 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
...
@@ -165,6 +165,77 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
return
fi
,
nil
return
fi
,
nil
}
}
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func
(
f
*
File
)
read
(
b
[]
byte
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Read
(
f
.
fd
,
b
)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func
(
f
*
File
)
pread
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
curoffset
,
e
:=
syscall
.
Seek
(
f
.
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
syscall
.
Seek
(
f
.
fd
,
curoffset
,
0
)
o
:=
syscall
.
Overlapped
{
OffsetHigh
:
uint32
(
off
>>
32
),
Offset
:
uint32
(
off
),
}
var
done
uint32
e
=
syscall
.
ReadFile
(
int32
(
f
.
fd
),
b
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
write
(
b
[]
byte
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Write
(
f
.
fd
,
b
)
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func
(
f
*
File
)
pwrite
(
b
[]
byte
,
off
int64
)
(
n
int
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
curoffset
,
e
:=
syscall
.
Seek
(
f
.
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
syscall
.
Seek
(
f
.
fd
,
curoffset
,
0
)
o
:=
syscall
.
Overlapped
{
OffsetHigh
:
uint32
(
off
>>
32
),
Offset
:
uint32
(
off
),
}
var
done
uint32
e
=
syscall
.
WriteFile
(
int32
(
f
.
fd
),
b
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func
(
f
*
File
)
seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
int
)
{
f
.
l
.
Lock
()
defer
f
.
l
.
Unlock
()
return
syscall
.
Seek
(
f
.
fd
,
offset
,
whence
)
}
// Truncate changes the size of the named file.
// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
// If the file is a symbolic link, it changes the size of the link's target.
func
Truncate
(
name
string
,
size
int64
)
Error
{
func
Truncate
(
name
string
,
size
int64
)
Error
{
...
...
src/pkg/syscall/syscall_windows.go
View file @
b1deb3be
...
@@ -250,27 +250,6 @@ func Read(fd int, p []byte) (n int, errno int) {
...
@@ -250,27 +250,6 @@ func Read(fd int, p []byte) (n int, errno int) {
return
int
(
done
),
0
return
int
(
done
),
0
}
}
// TODO(brainman): ReadFile/WriteFile change file offset, therefore
// i use Seek here to preserve semantics of unix pread/pwrite,
// not sure if I should do that
func
Pread
(
fd
int
,
p
[]
byte
,
offset
int64
)
(
n
int
,
errno
int
)
{
curoffset
,
e
:=
Seek
(
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
Seek
(
fd
,
curoffset
,
0
)
var
o
Overlapped
o
.
OffsetHigh
=
uint32
(
offset
>>
32
)
o
.
Offset
=
uint32
(
offset
)
var
done
uint32
e
=
ReadFile
(
int32
(
fd
),
p
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
func
Write
(
fd
int
,
p
[]
byte
)
(
n
int
,
errno
int
)
{
func
Write
(
fd
int
,
p
[]
byte
)
(
n
int
,
errno
int
)
{
var
done
uint32
var
done
uint32
e
:=
WriteFile
(
int32
(
fd
),
p
,
&
done
,
nil
)
e
:=
WriteFile
(
int32
(
fd
),
p
,
&
done
,
nil
)
...
@@ -280,23 +259,6 @@ func Write(fd int, p []byte) (n int, errno int) {
...
@@ -280,23 +259,6 @@ func Write(fd int, p []byte) (n int, errno int) {
return
int
(
done
),
0
return
int
(
done
),
0
}
}
func
Pwrite
(
fd
int
,
p
[]
byte
,
offset
int64
)
(
n
int
,
errno
int
)
{
curoffset
,
e
:=
Seek
(
fd
,
0
,
1
)
if
e
!=
0
{
return
0
,
e
}
defer
Seek
(
fd
,
curoffset
,
0
)
var
o
Overlapped
o
.
OffsetHigh
=
uint32
(
offset
>>
32
)
o
.
Offset
=
uint32
(
offset
)
var
done
uint32
e
=
WriteFile
(
int32
(
fd
),
p
,
&
done
,
&
o
)
if
e
!=
0
{
return
0
,
e
}
return
int
(
done
),
0
}
func
Seek
(
fd
int
,
offset
int64
,
whence
int
)
(
newoffset
int64
,
errno
int
)
{
func
Seek
(
fd
int
,
offset
int64
,
whence
int
)
(
newoffset
int64
,
errno
int
)
{
var
w
uint32
var
w
uint32
switch
whence
{
switch
whence
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment