@@ -323,20 +323,27 @@ func (s *SocketOperations) Write(ctx context.Context, _ *fs.File, src usermem.IO
323323 f := & ioSequencePayload {ctx : ctx , src : src }
324324 n , resCh , err := s .Endpoint .Write (f , tcpip.WriteOptions {})
325325 if err == tcpip .ErrWouldBlock {
326- return int64 ( n ) , syserror .ErrWouldBlock
326+ return 0 , syserror .ErrWouldBlock
327327 }
328328
329329 if resCh != nil {
330330 t := ctx .(* kernel.Task )
331331 if err := t .Block (resCh ); err != nil {
332- return int64 ( n ) , syserr .FromError (err ).ToError ()
332+ return 0 , syserr .FromError (err ).ToError ()
333333 }
334334
335335 n , _ , err = s .Endpoint .Write (f , tcpip.WriteOptions {})
336- return int64 (n ), syserr .TranslateNetstackError (err ).ToError ()
337336 }
338337
339- return int64 (n ), syserr .TranslateNetstackError (err ).ToError ()
338+ if err != nil {
339+ return 0 , syserr .TranslateNetstackError (err ).ToError ()
340+ }
341+
342+ if int64 (n ) < src .NumBytes () {
343+ return int64 (n ), syserror .ErrWouldBlock
344+ }
345+
346+ return int64 (n ), nil
340347}
341348
342349// Readiness returns a mask of ready events for socket s.
@@ -1343,11 +1350,16 @@ func (s *SocketOperations) SendMsg(t *kernel.Task, src usermem.IOSequence, to []
13431350 n , resCh , err := s .Endpoint .Write (tcpip .SlicePayload (v ), opts )
13441351 if resCh != nil {
13451352 if err := t .Block (resCh ); err != nil {
1346- return int ( n ) , syserr .FromError (err )
1353+ return 0 , syserr .FromError (err )
13471354 }
13481355 n , _ , err = s .Endpoint .Write (tcpip .SlicePayload (v ), opts )
13491356 }
1350- if err != tcpip .ErrWouldBlock || flags & linux .MSG_DONTWAIT != 0 {
1357+ dontWait := flags & linux .MSG_DONTWAIT != 0
1358+ if err == nil && (n >= uintptr (len (v )) || dontWait ) {
1359+ // Complete write.
1360+ return int (n ), nil
1361+ }
1362+ if err != nil && (err != tcpip .ErrWouldBlock || dontWait ) {
13511363 return int (n ), syserr .TranslateNetstackError (err )
13521364 }
13531365
@@ -1363,11 +1375,17 @@ func (s *SocketOperations) SendMsg(t *kernel.Task, src usermem.IOSequence, to []
13631375 n , _ , err = s .Endpoint .Write (tcpip .SlicePayload (v ), opts )
13641376 v .TrimFront (int (n ))
13651377 total += n
1366- if err != tcpip .ErrWouldBlock {
1367- return int (total ), syserr .TranslateNetstackError (err )
1378+
1379+ if err != nil && err != tcpip .ErrWouldBlock && total == 0 {
1380+ return 0 , syserr .TranslateNetstackError (err )
1381+ }
1382+
1383+ if err == nil && len (v ) == 0 || err != nil && err != tcpip .ErrWouldBlock {
1384+ return int (total ), nil
13681385 }
13691386
13701387 if err := t .Block (ch ); err != nil {
1388+ // handleIOError will consume errors from t.Block if needed.
13711389 return int (total ), syserr .FromError (err )
13721390 }
13731391 }
0 commit comments