X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/9981c27ef1ebc3844a646392fc1c52416af699ca..860236bf90087c88e886b6a7bffb83d6df51c1cc:/io.c diff --git a/io.c b/io.c index 7e02d348..b0bdabe8 100644 --- a/io.c +++ b/io.c @@ -56,6 +56,7 @@ extern struct stats stats; const char phase_unknown[] = "unknown"; int select_timeout = SELECT_TIMEOUT; +int ignore_timeout = 0; int batch_fd = -1; int batch_gen_fd = -1; @@ -75,9 +76,8 @@ int batch_gen_fd = -1; const char *io_write_phase = phase_unknown; const char *io_read_phase = phase_unknown; -/** Ignore EOF errors while reading a module listing if the remote - version is 24 or less. */ -int kludge_around_eof = False; +/* Ignore an EOF error if non-zero. See whine_about_eof(). */ +int kluge_around_eof = 0; int msg_fd_in = -1; int msg_fd_out = -1; @@ -137,7 +137,7 @@ static void check_timeout(void) { time_t t; - if (!io_timeout) + if (!io_timeout || ignore_timeout) return; if (!last_io) { @@ -361,20 +361,28 @@ void io_set_filesfrom_fds(int f_in, int f_out) io_filesfrom_buflen = 0; } -/** - * It's almost always an error to get an EOF when we're trying to read - * from the network, because the protocol is self-terminating. +/* It's almost always an error to get an EOF when we're trying to read from the + * network, because the protocol is (for the most part) self-terminating. * - * However, there is one unfortunate cases where it is not, which is - * rsync <2.4.6 sending a list of modules on a server, since the list - * is terminated by closing the socket. So, for the section of the - * program where that is a problem (start_socket_client), - * kludge_around_eof is True and we just exit. - */ + * There is one case for the receiver when it is at the end of the transfer + * (hanging around reading any keep-alive packets that might come its way): if + * the sender dies before the generator's kill-signal comes through, we can end + * up here needing to loop until the kill-signal arrives. 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 void whine_about_eof(int fd) { - if (kludge_around_eof && fd == sock_f_in) - exit_cleanup(0); + if (kluge_around_eof && fd == sock_f_in) { + int i; + if (kluge_around_eof > 0) + exit_cleanup(0); + /* If we're still here after 10 seconds, exit with an error. */ + for (i = 10*1000/20; i--; ) + msleep(20); + } rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed " "(%.0f bytes received so far) [%s]\n", @@ -634,6 +642,21 @@ void io_end_buffering(void) } +void maybe_send_keepalive(int allowed_lull, int ndx) +{ + if (time(NULL) - last_io >= allowed_lull) { + if (!iobuf_out || !iobuf_out_cnt) { + if (protocol_version < 29) + return; /* there's nothing we can do */ + write_int(sock_f_out, ndx); + write_shortint(sock_f_out, ITEM_IS_NEW); + } + if (iobuf_out) + io_flush(NORMAL_FLUSH); + } +} + + /** * Continue trying to read len bytes - don't return until len has been * read. @@ -1014,6 +1037,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len) * to grab any messages they sent before they died. */ while (fd == sock_f_out && io_multiplexing_in) { io_timeout = select_timeout = 30; + ignore_timeout = 0; readfd_unbuffered(sock_f_in, io_filesfrom_buf, sizeof io_filesfrom_buf); }