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/

Reply via email to