On Tue, May 09, 2006 at 03:54:16PM +0100, Dave Korn wrote: > > 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.
Well 85% of it was honestly whining in retrospect. > > 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(). > > cheers, > DaveK Thanks for taking the time to go through the original mail Dave - I appreciate it. After refactoring (just kidding, I don't really subscrib to that word)^H^H modifying my original n_recv_iov() code to deal with the edge-of-MSS and other partial readv() occurences I'm not having a problem anymore - unsurprisingly. I actually just call my n_recv() (standard non-blocking linear read) to read remaining bytes of a partially filled vector because I'd rather not muck with the contents of the original iovec passed in. I just pass it to n_iov_offset() with the bytes read as a value-result argument which returns number of iovecs filled + offset within a partially filled iovec in the v-r arg. So far so good, but if anyone sees anything glaring might as well point it out - although this is not really CW related at this point. -cl New stuff: 400 size_t n_iov_offset(const struct iovec *v, const size_t c, size_t *os) 401 { 402 size_t l, cv; 403 404 for (cv = 0; cv < c; cv++) { 405 if ((l = v[cv].iov_len) > *os) break; 406 *os -= l; 407 } 408 409 return cv; 410 } 411 412 size_t n_iov_total(const struct iovec *v, const size_t c) 413 { 414 size_t cv, bt; 415 416 for (cv = bt = 0; cv < c; cv++) 417 bt += v[cv].iov_len; 418 419 return bt; 420 } 421 422 size_t n_recv_iov(const int s, const struct iovec *v, size_t c, int tout) 423 { 424 size_t cv, br, bre, brt = 0; 425 int res; 426 struct timeval to; 427 fd_set fds, fds_m; 428 429 FD_ZERO(&fds_m); 430 FD_SET(s, &fds_m); 431 432 bre = n_iov_total(v, c); 433 434 while (brt < bre) { 435 fds = fds_m; 436 to.tv_sec = tout; 437 to.tv_usec = 0; 438 439 if ((br = readv(s, v, c)) == (size_t)-1) { 440 switch (errno) { 441 case EWOULDBLOCK: 442 case EINTR: 443 break; 444 default: 445 perror("readv"); 446 return -1; 447 } 448 } else if (br) { 449 if ((brt += br) < bre) { 450 /* short read, mid-vector offset returned in br */ 451 cv = n_iov_offset(v, c, &br); 452 v += cv; 453 c -= cv; 454 455 if (br == 0) 456 continue; 457 458 /* call read if we're short mid-vector */ 459 br = n_recv(s, (char *)v->iov_base + br, 460 v->iov_len - br, tout); 461 if (br == (size_t)-1) 462 return -1; 463 464 /* done with mid-vector fill, proceed with rest */ 465 brt += br; 466 v++; 467 c--; 468 } 469 } else { 470 break; 471 } 472 473 if ((res = select(s + 1, &fds, NULL, NULL, &to)) == 0) 474 return -1; /* timeout */ 475 else if (res == -1) { 476 perror("select"); /* never happen */ 477 return -1; 478 } 479 } 480 481 return brt; 482 } -- 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/