Mail Archives: cygwin/2006/05/09/10:01:22
On Tuesday, May 09, 2006 12:44 AM clayne wrote:
> [...]
>
> My actual readv() wrapping code is very basic and standard, so I don't
> think
> it's doing anything evil or causing a problem:
>
> 400 size_t n_recv_iov(int s, const struct iovec *v, size_t c, int
> tout)
> 401 {
> 402 size_t br;
> 403 int res;
> 404 struct timeval to;
> 405 fd_set fds, fds_m;
> 406
> 407 FD_ZERO(&fds_m);
> 408 FD_SET(s, &fds_m);
> 409
> 410 while (1) {
> 411 fds = fds_m;
> 412 to.tv_sec = tout;
> 413 to.tv_usec = 0;
> 414
> 415 if ((br = readv(s, v, c)) == (size_t)-1) {
> 416 switch (errno) {
> 417 case EWOULDBLOCK:
> 418 case EINTR:
> 419 break;
> 420 default:
> 421 perror("readv");
> 422 return -1;
> 423 }
> 424 } else {
> 425 break;
> 426 }
> 427
> 428 if ((res = select(s + 1, &fds, NULL, NULL, &to))
> == 0)
> 429 return -1; /* timeout */
> 430 else if (res == -1) {
> 431 perror("select");
> 432 return -1; /* never happen */
> 433 }
> 434 }
> 435
> 436 return br;
> 437 }
>
> And my call to it is basic as well:
>
> 61 IOV_SET(&packet[0], &byte_tl, sizeof(byte_tl));
> 62 IOV_SET(&packet[1], &byte_vl, sizeof(byte_vl));
> 63 IOV_SET(&packet[2], &byte_flags, sizeof(byte_flags));
> 64 IOV_SET(&packet[3], &nbo_s, sizeof(nbo_s));
> 65 IOV_SET(&packet[4], &nbo_t_onl, sizeof(nbo_t_onl));
> 66 IOV_SET(&packet[5], &nbo_t_ofl, sizeof(nbo_t_ofl));
> 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
--
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 -