Subject: Re: readv() questions
From: [email-masked]
To: Mark Pizzolato <[email-masked]>
Cc: [email-masked]
Date: Tue, 9 May 2006 07:35:56 -0700

On Tue, May 09, 2006 at 07:00:57AM -0700, Mark Pizzolato wrote:
> >     67
> >     68         for (error = 0; !error; ) {
> >     69                 error = 1;
> >     70
> >     71                 if ((hl = n_recv_iov(s, packet, NE(packet), 60)) 
> >== (size_t)-1)
> >     72                         break;
> >     73
> >     74 assert(byte_vl < sizeof(byte_var));
> >     75
> >     76                 if ((vl = n_recv(s, byte_var, byte_vl, 60)) == 
> >(size_t)-1)
> >     77                         break;
> >     78                 if (hl == 0 || vl == 0)
> >     79                         break;
> >     80
> >     81                 error = 0;
> >     82
> >     83                 /* process_data(); */
> >     84         }
> >
> >Sorry for the ultra mail, but I know for a fact that readv() on cygwin is
> >doing bad things when faced with a lot of data to read from the wire. Any
> >insights?
> 
> Well, to me this looks like a variation on the classic error made when 
> coding applications which use tcp.  Specifically that there is a 1<->1 
> crrespondence between sends( write, writev, etc) on the sending side to 
> rcvs(read, readv, etc) on the recieving side.  TCP makes no such guarantee. 
> It only guarantees tha the bytes put in on the sending side of the 
> connection will come out in the same order on the recieving side.  No 
> guarantee about the size of the respective reads of the data delivered.  If 
> you are expecting to receive a certain size data element, the burden is 
> yours to actually make sure you get as much data as you expect, and to 
> continue reading until you are happy.
> 
> Your code does not seem to do anything to validate that the length of the 
> data returned by readv is indeed what you expected.
> 
> - Mark Pizzolato 

Understood, there are actually other assertions that I had not layed out in
the email - the code I use has a lot of other trivial checks just for this
type of situation. However, what exactly is one supposed to do when readv()
returns a short count within a stream of data? One is totally screwed and
must request retransmission entirely or wrap it all with a minimal protocol
that can handle a rerequest with an offset for x number of other items -
nevermind the fact that one just dumped a bit on wire that is actually
valid data but is no longer usable without heavy reassembly. You cannot
even use the idiom of "well let me just get the rest of this here and I'll
make a request for the dropped data after." If that's the cake to eat,
then I'll just rewrite my readv wrapper to deal with it I guess. Not like
that is trivial if data is disrupted mid-vector. :-|

From a Solaris manpage (not Cygwin, but a likewise reasonable POSIX
implementation):

--
     Each iovec entry specifies the base address and length of an area  in
     memory  where  data should be placed.  The readv() function always
     fills an area completely  before  proceeding to the next.

RETURN VALUES
     Upon successful completion,  read()  and  readv()  return  a
     non-negative integer indicating the number of bytes actually
     read. Otherwise, the functions return -1 and  set  errno  to indicate
     the error.
--

Technically this doesn't specify it will always return what's requested
(just like read() wouldn't in NB mode) so I guess onus is still on me. I'll
try to work out a simple test case after re-examining other options for
dealing with it in my readv() underlying call.

-cl

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/