Make sure a write error drains any messages in the input buffer.
#include "case_N.h"
if (exit_code && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1
#include "case_N.h"
if (exit_code && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1
- && (protocol_version >= 31 || am_server || (!am_sender && !am_generator))) {
+ && (protocol_version >= 31 || (!am_sender && !am_generator))) {
if (line > 0)
send_msg_int(MSG_ERROR_EXIT, exit_code);
noop_io_until_death();
if (line > 0)
send_msg_int(MSG_ERROR_EXIT, exit_code);
noop_io_until_death();
static flist_ndx_list redo_list, hlink_list;
static flist_ndx_list redo_list, hlink_list;
+static void drain_multiplex_messages(void);
static void sleep_for_bwlimit(int bytes_written);
static void check_timeout(void)
static void sleep_for_bwlimit(int bytes_written);
static void check_timeout(void)
* There is another case for older protocol versions (< 24) where the module
* listing was not terminated, so we must ignore an EOF error in that case and
* exit. In this situation, kluge_around_eof will be > 0. */
* There is another case for older protocol versions (< 24) where the module
* listing was not terminated, so we must ignore an EOF error in that case and
* exit. In this situation, kluge_around_eof will be > 0. */
-static NORETURN void whine_about_eof(int fd)
+static NORETURN void whine_about_eof(BOOL allow_kluge)
- if (kluge_around_eof && fd == sock_f_in) {
+ if (kluge_around_eof && allow_kluge) {
int i;
if (kluge_around_eof > 0)
exit_cleanup(0);
int i;
if (kluge_around_eof > 0)
exit_cleanup(0);
if (max_fd < 0) {
switch (flags & PIO_NEED_FLAGS) {
case PIO_NEED_INPUT:
if (max_fd < 0) {
switch (flags & PIO_NEED_FLAGS) {
case PIO_NEED_INPUT:
+ iobuf.in.len = 0;
+ if (kluge_around_eof == 2)
+ exit_cleanup(0);
+ if (iobuf.in_fd == -2)
+ whine_about_eof(True);
rprintf(FERROR, "error in perform_io: no fd for input.\n");
exit_cleanup(RERR_PROTOCOL);
case PIO_NEED_OUTROOM:
case PIO_NEED_MSGROOM:
msgs2stderr = 1;
rprintf(FERROR, "error in perform_io: no fd for input.\n");
exit_cleanup(RERR_PROTOCOL);
case PIO_NEED_OUTROOM:
case PIO_NEED_MSGROOM:
msgs2stderr = 1;
+ drain_multiplex_messages();
+ if (iobuf.out_fd == -2)
+ whine_about_eof(True);
rprintf(FERROR, "error in perform_io: no fd for output.\n");
exit_cleanup(RERR_PROTOCOL);
default:
rprintf(FERROR, "error in perform_io: no fd for output.\n");
exit_cleanup(RERR_PROTOCOL);
default:
int n;
if ((n = read(iobuf.in_fd, iobuf.in.buf + pos, len)) <= 0) {
if (n == 0) {
int n;
if ((n = read(iobuf.in_fd, iobuf.in.buf + pos, len)) <= 0) {
if (n == 0) {
+ /* Signal that input has become invalid. */
if (!read_batch || batch_fd < 0 || am_generator)
if (!read_batch || batch_fd < 0 || am_generator)
- whine_about_eof(iobuf.in_fd); /* Doesn't return. */
batch_fd = -1;
continue;
}
batch_fd = -1;
continue;
}
else {
/* Don't write errors on a dead socket. */
msgs2stderr = 1;
else {
/* Don't write errors on a dead socket. */
msgs2stderr = 1;
- out->len = iobuf.raw_flushing_ends_before = out->pos = 0;
+ iobuf.out_fd = -2;
+ iobuf.out.len = iobuf.msg.len = iobuf.raw_flushing_ends_before = 0;
rsyserr(FERROR_SOCKET, errno, "[%s] write error", who_am_i());
rsyserr(FERROR_SOCKET, errno, "[%s] write error", who_am_i());
+ drain_multiplex_messages();
exit_cleanup(RERR_STREAMIO);
}
}
exit_cleanup(RERR_STREAMIO);
}
}
/* For protocol 31: setting an I/O timeout ensures that if something
* inexplicably weird happens, we won't hang around forever. For older
* protocols: we can't tell the other side to die, so we linger a brief
/* For protocol 31: setting an I/O timeout ensures that if something
* inexplicably weird happens, we won't hang around forever. For older
* protocols: we can't tell the other side to die, so we linger a brief
+static void drain_multiplex_messages(void)
+{
+ while (IN_MULTIPLEXED && iobuf.in.len) {
+ if (iobuf.raw_input_ends_before) {
+ size_t raw_len = iobuf.raw_input_ends_before - iobuf.in.pos;
+ iobuf.raw_input_ends_before = 0;
+ if (raw_len >= iobuf.in.len) {
+ iobuf.in.len = 0;
+ break;
+ }
+ iobuf.in.pos += raw_len;
+ iobuf.in.len -= raw_len;
+ }
+ read_a_msg();
+ }
+}
+
void wait_for_receiver(void)
{
if (!iobuf.raw_input_ends_before)
void wait_for_receiver(void)
{
if (!iobuf.raw_input_ends_before)
{
if (f != iobuf.in_fd) {
if (safe_read(f, buf, len) != len)
{
if (f != iobuf.in_fd) {
if (safe_read(f, buf, len) != len)
- whine_about_eof(f); /* Doesn't return. */
+ whine_about_eof(False); /* Doesn't return. */