comparison common-channel.c @ 1192:af940cefdba1

Fix "Avoid queueing into circbuffer when the channel is about to close" which broken handling EAGAIN/EINTR
author Matt Johnston <matt@ucc.asn.au>
date Fri, 27 Nov 2015 22:19:08 +0800
parents b370b4b172d0
children 750ec4ec4cbe
comparison
equal deleted inserted replaced
1191:b370b4b172d0 1192:af940cefdba1
443 if (errno != EINTR && errno != EAGAIN) { 443 if (errno != EINTR && errno != EAGAIN) {
444 TRACE(("channel IO write error fd %d %s", fd, strerror(errno))) 444 TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
445 close_chan_fd(channel, fd, SHUT_WR); 445 close_chan_fd(channel, fd, SHUT_WR);
446 return DROPBEAR_FAILURE; 446 return DROPBEAR_FAILURE;
447 } 447 }
448 } 448 } else {
449 cbuf_incrread(cbuf, written); 449 cbuf_incrread(cbuf, written);
450 channel->recvdonelen += written; 450 channel->recvdonelen += written;
451 }
451 return DROPBEAR_SUCCESS; 452 return DROPBEAR_SUCCESS;
452 } 453 }
453 #endif /* !HAVE_WRITEV */ 454 #endif /* !HAVE_WRITEV */
454 455
455 #ifdef HAVE_WRITEV 456 #ifdef HAVE_WRITEV
458 459
459 struct iovec iov[3]; 460 struct iovec iov[3];
460 unsigned char *circ_p1, *circ_p2; 461 unsigned char *circ_p1, *circ_p2;
461 unsigned int circ_len1, circ_len2; 462 unsigned int circ_len1, circ_len2;
462 int io_count = 0; 463 int io_count = 0;
463 int cbuf_written; 464
464 ssize_t written; 465 ssize_t written;
465 466
466 cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2); 467 cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
467 468
468 if (circ_len1 > 0) { 469 if (circ_len1 > 0) {
506 if (errno != EINTR && errno != EAGAIN) { 507 if (errno != EINTR && errno != EAGAIN) {
507 TRACE(("channel IO write error fd %d %s", fd, strerror(errno))) 508 TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
508 close_chan_fd(channel, fd, SHUT_WR); 509 close_chan_fd(channel, fd, SHUT_WR);
509 return DROPBEAR_FAILURE; 510 return DROPBEAR_FAILURE;
510 } 511 }
511 } 512 } else {
512 513 int cbuf_written = MIN(circ_len1+circ_len2, (unsigned int)written);
513 cbuf_written = MIN(circ_len1+circ_len2, (unsigned int)written); 514 cbuf_incrread(cbuf, cbuf_written);
514 cbuf_incrread(cbuf, cbuf_written); 515 if (morelen) {
515 if (morelen) { 516 *morelen = written - cbuf_written;
516 *morelen = written - cbuf_written; 517 }
517 } 518 channel->recvdonelen += written;
518 channel->recvdonelen += written; 519 }
519 return DROPBEAR_SUCCESS; 520 return DROPBEAR_SUCCESS;
520 } 521 }
521 #endif /* HAVE_WRITEV */ 522 #endif /* HAVE_WRITEV */
522 523
523 /* Called to write data out to the local side of the channel. 524 /* Called to write data out to the local side of the channel.