delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2006/05/09/10:36:07

X-Spam-Check-By: sourceware.org
Date: Tue, 9 May 2006 07:35:56 -0700
From: clayne AT anodized DOT com
To: Mark Pizzolato <list-cygwin AT subscriptions DOT pizzolato DOT net>
Cc: cygwin AT cygwin DOT com
Subject: Re: readv() questions
Message-ID: <20060509143556.GI18330@ns1.anodized.com>
References: <20060509074420 DOT GG18330 AT ns1 DOT anodized DOT com> <001001c67371$004cf520$1f3ca8c0 AT AlohaSunset DOT com>
Mime-Version: 1.0
In-Reply-To: <001001c67371$004cf520$1f3ca8c0@AlohaSunset.com>
User-Agent: Mutt/1.5.11
X-Assp-Spam-Prob: 0.00000
X-Assp-Whitelisted: Yes
X-Assp-Envelope-From: clayne AT ns1 DOT anodized DOT com
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

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/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019