Fix SO_ERROR behavior for TCP in gVisor.

Fixes the behaviour of SO_ERROR for tcp sockets where in linux it returns
sk->sk_err and if sk->sk_err is 0 then it returns sk->sk_soft_err. In gVisor TCP
we endpoint.HardError is the equivalent of sk->sk_err and endpoint.LastError
holds soft errors. This change brings this into alignment with Linux such that
both hard/soft errors are cleared when retrieved using getsockopt(.. SO_ERROR)
is called on a socket.

Fixes #3812

PiperOrigin-RevId: 342868552
This commit is contained in:
Bhasker Hariharan
2020-11-17 08:33:03 -08:00
committed by gVisor bot
parent 938aabeecb
commit fb9a649f39
9 changed files with 241 additions and 59 deletions
+9 -4
View File
@@ -2686,7 +2686,7 @@ func (s *socketOpsCommon) coalescingRead(ctx context.Context, dst usermem.IOSequ
// Always do at least one fetchReadView, even if the number of bytes to
// read is 0.
err = s.fetchReadView()
if err != nil {
if err != nil || len(s.readView) == 0 {
break
}
if dst.NumBytes() == 0 {
@@ -2709,15 +2709,20 @@ func (s *socketOpsCommon) coalescingRead(ctx context.Context, dst usermem.IOSequ
}
copied += n
s.readView.TrimFront(n)
if len(s.readView) == 0 {
atomic.StoreUint32(&s.readViewHasData, 0)
}
dst = dst.DropFirst(n)
if e != nil {
err = syserr.FromError(e)
break
}
// If we are done reading requested data then stop.
if dst.NumBytes() == 0 {
break
}
}
if len(s.readView) == 0 {
atomic.StoreUint32(&s.readViewHasData, 0)
}
// If we managed to copy something, we must deliver it.