This is the mail archive of the
cygwin
mailing list for the Cygwin project.
Re: readv() questions
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/