This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: readv() questions

On 09 May 2006 15:36, clayne@anodized wrote:

>> 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.

>> Your code does not seem to do anything to validate that the length of the
>> data returned by readv is indeed what you expected.

> type of situation. However, what exactly is one supposed to do when readv()
> returns a short count within a stream of data? 

  *Exactly* the same as when a call to read() ends early:  subtract the amount
you received this time from the total amount you want to receive, advance the
buffer pointer, and try again.

> One is totally screwed and
> must request retransmission entirely or wrap 

  Nonsense!  You got part of the data, the rest is waiting for you to read it.
Why should you want a retransmission?

> nevermind the fact that one just dumped a bit on wire that is actually
> valid data but is no longer usable without heavy reassembly. 

  Now what are you talking about?  TCP does the heavy reassembly for you.  If
you call having to restart a partial read "heavy reassembly" you're really not
aware of how much more goes into IP defragmentation and TCP stream 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."

  Yes you absolutely can.  Who said you can't?  You're just not trying.  It
works fine.

> 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. :-|

  Yes, it so is trivial.  It's barely the tiniest bit more complex than
dealing with restarting a call to read().

> 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.

  Yes.  Of course, what you haven't grokked is that if it doesn't fill an area
completely, owing to a partial read satisfaction, it *also* doesn't go on to
the next.

>      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. 

  Always has been, always was.  Readv behaves like a bunch of calls to read,
each one of which only takes place if the previous one completed *fully*.

> I'll
> try to work out a simple test case after re-examining other options for
> dealing with it in my readv() underlying call.

  Well, by analogy to the bog-standard way of dealing with partial read()
completions, you would take the number of bytes returned, see how many of the
iov arrray must have been completely satisfied by summing the lengths, then
restart the one that failed and the remaining ones by advancing the iov array
pointer and decrementing the iovcnt to skip the completed iov entries, adjust
the base and length of the iov entry you're restarting to allow for however
many bytes partially filled it, and off you go.

Can't think of a witty .sigline today....

Unsubscribe info:
Problem reports:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]