Change os.Error convention:
echo back context of call in error if likely to be useful.
For example, if os.Open("/etc/passwd", os.O_RDONLY)
fails with syscall.EPERM, it returns as the os.Error
&PathError{
Op: "open",
Path: "/etc/passwd"
Error: os.EPERM
}
which formats as
open /etc/passwd: permission denied
Not converted:
datafmt
go/...
google/...
regexp
tabwriter
template
R=r
DELTA=1153 (561 added, 156 deleted, 436 changed)
OCL=30738
CL=30781
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 17598af..0917c50 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -85,7 +85,7 @@
var e int;
if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
Errno:
- err = os.ErrnoToError(e);
+ err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)};
Error:
s.pr.Close();
s.pw.Close();
@@ -304,19 +304,46 @@
once.Do(_StartServer);
}
if e := syscall.SetNonblock(fd, true); e != 0 {
- return nil, os.ErrnoToError(e);
+ return nil, &os.PathError{"setnonblock", laddr, os.Errno(e)};
}
f = new(netFD);
f.fd = fd;
f.net = net;
f.laddr = laddr;
f.raddr = raddr;
- f.file = os.NewFile(fd, "net: " + net + " " + laddr + " " + raddr);
+ f.file = os.NewFile(fd, net + "!" + laddr + "->" + raddr);
f.cr = make(chan *netFD, 1);
f.cw = make(chan *netFD, 1);
return f, nil
}
+func isEAGAIN(e os.Error) bool {
+ if e1, ok := e.(*os.PathError); ok {
+ return e1.Error == os.EAGAIN;
+ }
+ return e == os.EAGAIN;
+}
+
+func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error)
+
+func (fd *netFD) addr() string {
+ sa, e := syscall.Getsockname(fd.fd);
+ if e != 0 {
+ return "";
+ }
+ addr, err := sockaddrToString(sa);
+ return addr;
+}
+
+func (fd *netFD) remoteAddr() string {
+ sa, e := syscall.Getpeername(fd.fd);
+ if e != 0 {
+ return "";
+ }
+ addr, err := sockaddrToString(sa);
+ return addr;
+}
+
func (fd *netFD) Close() os.Error {
if fd == nil || fd.file == nil {
return os.EINVAL
@@ -338,7 +365,7 @@
func (fd *netFD) Read(p []byte) (n int, err os.Error) {
if fd == nil || fd.file == nil {
- return -1, os.EINVAL
+ return 0, os.EINVAL
}
fd.rio.Lock();
defer fd.rio.Unlock();
@@ -347,17 +374,20 @@
} else {
fd.rdeadline = 0;
}
- n, err = fd.file.Read(p);
- for err == os.EAGAIN && fd.rdeadline >= 0 {
- pollserver.WaitRead(fd);
- n, err = fd.file.Read(p)
+ for {
+ n, err = fd.file.Read(p);
+ if isEAGAIN(err) && fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd);
+ continue;
+ }
+ break;
}
- return n, err
+ return;
}
func (fd *netFD) Write(p []byte) (n int, err os.Error) {
if fd == nil || fd.file == nil {
- return -1, os.EINVAL
+ return 0, os.EINVAL
}
fd.wio.Lock();
defer fd.wio.Unlock();
@@ -376,7 +406,7 @@
if nn == len(p) {
break;
}
- if err == os.EAGAIN && fd.wdeadline >= 0 {
+ if isEAGAIN(err) && fd.wdeadline >= 0 {
pollserver.WaitWrite(fd);
continue;
}
@@ -387,8 +417,6 @@
return nn, err
}
-func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error)
-
func (fd *netFD) accept() (nfd *netFD, err os.Error) {
if fd == nil || fd.file == nil {
return nil, os.EINVAL
@@ -411,7 +439,7 @@
}
if e != 0 {
syscall.ForkLock.RUnlock();
- return nil, os.ErrnoToError(e)
+ return nil, &os.PathError{"accept", fd.addr(), os.Errno(e)}
}
syscall.CloseOnExec(s);
syscall.ForkLock.RUnlock();
@@ -426,23 +454,3 @@
}
return nfd, nil
}
-
-func (fd *netFD) addr() string {
- sa, err := syscall.Getsockname(fd.fd);
- if err != 0 {
- return "";
- }
- // TODO(rsc): woud like to say err not err1 but 6g complains
- addr, err1 := sockaddrToString(sa);
- return addr;
-}
-
-func (fd *netFD) remoteAddr() string {
- sa, err := syscall.Getpeername(fd.fd);
- if err != 0 {
- return "";
- }
- // TODO(rsc): woud like to say err not err1 but 6g complains
- addr, err1 := sockaddrToString(sa);
- return addr;
-}