From: Wayne Davison Date: Wed, 23 Dec 2009 19:31:28 +0000 (-0800) Subject: Revert to having the receiver handle timeouts on the receiving side. X-Git-Tag: v3.0.7pre2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae358c1960a64dbdab82905e43594e7805488e56;p=thirdparty%2Frsync.git Revert to having the receiver handle timeouts on the receiving side. This will give 3.0.7 the standard timeout handling with just a few improvements: a fix for the detection of recent sender I/O, the use of MSG_DATA for really old rsync versions, and better setting of select_timeout for shorter timeout settings. --- diff --git a/NEWS b/NEWS index 7f9bf188..b0040bb2 100644 --- a/NEWS +++ b/NEWS @@ -28,10 +28,9 @@ Changes since 3.0.6: - Improved the "--delete does not work without -r or -d" message. - - Improved rsync's handling of --timeout to avoid weird timeout cases and - to make keep-alive messages work even with older (pre-2.6.4) rsyncs (by - discovering a workable keep-alive signal that can be used with rsyncs - that don't support explicit keep-alive messages). + - Improved rsync's handling of --timeout to avoid a weird timeout case + where the sender could timeout even though it has recently written data + to the socket (but hasn't read data recently, due to the writing). - Some misc manpage improvements. diff --git a/generator.c b/generator.c index 7e32fe1f..9f3586ff 100644 --- a/generator.c +++ b/generator.c @@ -69,6 +69,7 @@ extern int io_error; extern int flist_eof; extern int allowed_lull; extern int sock_f_out; +extern int ignore_timeout; extern int protocol_version; extern int file_total; extern int fuzzy_basis; @@ -2211,6 +2212,12 @@ void generate_files(int f_out, const char *local_name) : "enabled"); } + /* Since we often fill up the outgoing socket and then just sit around + * waiting for the other 2 processes to do their thing, we don't want + * to exit on a timeout. If the data stops flowing, the receiver will + * notice that and let us know via the message pipe (or its closing). */ + ignore_timeout = 1; + dflt_perms = (ACCESSPERMS & ~orig_umask); do { diff --git a/io.c b/io.c index 578d2562..f9fa7c79 100644 --- a/io.c +++ b/io.c @@ -40,7 +40,6 @@ extern int allowed_lull; extern int am_server; extern int am_daemon; extern int am_sender; -extern int am_receiver; extern int am_generator; extern int inc_recurse; extern int io_error; @@ -62,6 +61,7 @@ extern iconv_t ic_send, ic_recv; #endif const char phase_unknown[] = "unknown"; +int ignore_timeout = 0; int batch_fd = -1; int msgdone_cnt = 0; @@ -123,11 +123,7 @@ static void check_timeout(void) { time_t t, chk; - /* On the receiving side, the generator is now handling timeouts, so - * the receiver ignores them. Note that the am_receiver flag is not - * set until the receiver forks from the generator, so timeouts will be - * based on receiving data on the receiving side until that event. */ - if (!io_timeout || am_receiver) + if (!io_timeout || ignore_timeout) return; t = time(NULL); @@ -215,13 +211,15 @@ void io_set_sock_fds(int f_in, int f_out) void set_io_timeout(int secs) { io_timeout = secs; + allowed_lull = (io_timeout + 1) / 2; - if (!io_timeout || io_timeout > SELECT_TIMEOUT) + if (!io_timeout || allowed_lull > SELECT_TIMEOUT) select_timeout = SELECT_TIMEOUT; else - select_timeout = io_timeout; + select_timeout = allowed_lull; - allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2; + if (read_batch) + allowed_lull = 0; } /* Setup the fd used to receive MSG_* messages. Only needed during the @@ -948,18 +946,19 @@ void maybe_flush_socket(int important) io_flush(NORMAL_FLUSH); } -/* Older rsync versions used to send either a MSG_NOOP (protocol 30) or a - * raw-data-based keep-alive (protocol 29), both of which implied forwarding of - * the message through the sender. Since the new timeout method does not need - * any forwarding, we just send an empty MSG_DATA message, which works with all - * rsync versions. This avoids any message forwarding, and leaves the raw-data - * stream alone (since we can never be quite sure if that stream is in the - * right state for a keep-alive message). */ void maybe_send_keepalive(void) { if (time(NULL) - last_io_out >= allowed_lull) { - if (!iobuf_out || !iobuf_out_cnt) - send_msg(MSG_DATA, "", 0, 0); + if (!iobuf_out || !iobuf_out_cnt) { + if (protocol_version < 29) + send_msg(MSG_DATA, "", 0, 0); + else if (protocol_version >= 30) + send_msg(MSG_NOOP, "", 0, 0); + else { + write_int(sock_f_out, cur_flist->used); + write_shortint(sock_f_out, ITEM_IS_NEW); + } + } if (iobuf_out) io_flush(NORMAL_FLUSH); } @@ -1043,7 +1042,6 @@ static int readfd_unbuffered(int fd, char *buf, size_t len) iobuf_in_ndx = 0; break; case MSG_NOOP: - /* Support protocol-30 keep-alive method. */ if (msg_bytes != 0) goto invalid_msg; if (am_sender) @@ -1526,6 +1524,7 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len) while (!am_server && fd == sock_f_out && io_multiplexing_in) { char buf[1024]; set_io_timeout(30); + ignore_timeout = 0; readfd_unbuffered(sock_f_in, buf, sizeof buf); } exit_cleanup(RERR_STREAMIO); diff --git a/rsync.h b/rsync.h index 5b20c5f3..d804d495 100644 --- a/rsync.h +++ b/rsync.h @@ -229,7 +229,7 @@ enum msgcode { MSG_FLIST=20, /* extra file list over sibling socket */ MSG_FLIST_EOF=21,/* we've transmitted all the file lists */ MSG_IO_ERROR=22,/* the sending side had an I/O error */ - MSG_NOOP=42, /* a do-nothing message (legacy protocol-30 only) */ + MSG_NOOP=42, /* a do-nothing message */ MSG_SUCCESS=100,/* successfully updated indicated flist index */ MSG_DELETED=101,/* successfully deleted a file on receiving side */ MSG_NO_SEND=102,/* sender failed to open a file we wanted */