anchor.diff:              %% We need to cancel this partial write.
               %%
               _ = cancel(SockRef, sendmsg, SendRef),
  -            {ok, do_sendmsg_rest(maps:get(iov, MsgHdr), Written)};
  -
  -
  +            {ok, sendmsg_rest(maps:get(iov, MsgHdr), Written)};
  +        %%
           select when (Deadline =:= nowait) ->
               ?SELECT(sendmsg, SendRef);
  -            
           select ->
   	    Timeout = timeout(Deadline),
               receive
                   {?ESOCK_TAG, #socket{ref = SockRef}, select, SendRef} ->
  -                    do_sendmsg(SockRef, MsgHdr, Flags, Deadline);
  -
  +                    sendmsg_loop(SockRef, MsgHdr, Flags, Deadline);
                   {?ESOCK_TAG, _Socket, abort, {SendRef, Reason}} ->
                       {error, Reason}
  -
               after Timeout ->
                       _ = cancel(SockRef, sendmsg, SendRef),
                       {error, timeout}
               end;
  -
  -
  -        {error, exbusy} = Error when Deadline =:= nowait -> Error;
  -
  -        {error, exbusy = Reason} ->
  +        %%
  +        {error, exbusy = Reason} when Deadline =/= nowait ->
               %% Internal error:
               %%   we called send, got eagain, and called send again
               %%   - without waiting for select message
               erlang:error(Reason);
  -
           {error, _} = ERROR ->
               ERROR
       end.
   
  -do_sendmsg_rest([B|IOVec], Written) when (Written >= byte_size(B)) ->
  -    do_sendmsg_rest(IOVec, Written - byte_size(B));
  -do_sendmsg_rest([B|IOVec], Written) ->
  +sendmsg_rest([B|IOVec], Written) when Written >= byte_size(B) ->
  +    sendmsg_rest(IOVec, Written - byte_size(B));
  +sendmsg_rest([B|IOVec], Written) ->
       <<_:Written/binary, Rest/binary>> = B,
       [Rest|IOVec].
   
  
positive.code:     case deadline(Timeout) of
          badarg = Reason ->
              erlang:error(Reason, [Socket, Length, Flags, Timeout]);
          Deadline ->
              do_recv(SockRef, Length, Flags, Deadline, <<>>)
      end;
  recv(Socket, Length, Flags, Timeout) ->
      erlang:error(badarg, [Socket, Length, Flags, Timeout]).
  
  %% We will only recurse with Length == 0 if Length is 0,
  %% so Length == 0 means to return all available data also when recursing
  %%
  %% Note that the Deadline value of 'nowait' has a special meaning. It means
  %% that we will either return with data or with the with {error, NNNN}. In
  %% wich case the caller will receive a select message at some later time.
  %%
  do_recv(SockRef, Length, Flags, Deadline, Acc) ->
  
      RecvRef = make_ref(),
  
      case prim_socket:recv(SockRef, RecvRef, Length, Flags) of
  
          {ok, Bin} ->
              {ok, bincat(Acc, Bin)};
  
  
          {more, Bin} ->
              %% There is more data readily available
              %% - repeat unless time's up
              %% Note: timeout(nowait) -> 0, so no recursion
              Timeout = timeout(Deadline),
              if
                  0 < Timeout ->
                      do_recv(
                        SockRef, Length, Flags, Deadline, bincat(Acc, Bin));
                  true ->
                      {ok, bincat(Acc, Bin)}
              end;
  
          {select, Bin} when Deadline =:= nowait ->
              %% We got a chunk but the caller will not wait
              {ok, {bincat(Acc, Bin), ?SELECT_INFO(recv, RecvRef)}};
  
          {select, Bin} ->
              %% We got a chunk
  	    Timeout = timeout(Deadline),
              receive
                  {?ESOCK_TAG, #socket{ref = SockRef}, select, RecvRef} ->
                      if
                          0 < Timeout ->
                              do_recv(
                                SockRef, Length - byte_size(Bin), Flags,
                                Deadline, bincat(Acc, Bin));
                          true ->
                              {error, {timeout, bincat(Acc, Bin)}}
                      end;
  
                  {?ESOCK_TAG, _Socket, abort, {RecvRef, Reason}} ->
                      {error, Reason}
  
              after Timeout ->
                      cancel(SockRef, recv, RecvRef),
                      {error, {timeout, bincat(Acc, Bin)}}
              end;
  
  
          select when Deadline =:= nowait ->
              %% The caller does not want to wait!
              %% The caller will be informed that there is something to read
              %% via the select socket message (see below).
              if
                  byte_size(Acc) =:= 0 ->
                      ?SELECT(recv, RecvRef);
                  true ->
                      {ok, {Acc, ?SELECT_INFO(recv, RecvRef)}}
              end;
  
          select when Length =:= 0, 0 < byte_size(Acc) ->
              %% We got some and are then asked to wait,
              %% but we only want the first that comes
              %% - cancel and return what we have
              cancel(SockRef, recv, RecvRef),
              {ok, Acc};
  
          select ->
              %% There is nothing just now, but we will be notified when there
              %% is something to read (a select message).
  
negative.code:         badarg = Reason ->
              erlang:error(Reason, [Socket, MsgHdr, Flags, Timeout]);
          Deadline ->
              sendmsg_loop(SockRef, MsgHdr, Flags, Deadline)
      end;
  sendmsg(Socket, MsgHdr, Flags, Timeout) ->
      erlang:error(badarg, [Socket, MsgHdr, Flags, Timeout]).
  
  sendmsg_loop(SockRef, MsgHdr, Flags, Deadline) ->
      SendRef = make_ref(),
      case prim_socket:sendmsg(SockRef, SendRef, MsgHdr, Flags) of
          ok ->
              %% We are done
              ok;
          %%
          {ok, Written} when is_integer(Written) andalso (Written > 0) ->
              %% We should not retry here since the protocol may not
              %% be able to handle a message being split. Leave it to
  