Adding --contimeout=SECONDS option.
authorWayne Davison <wayned@samba.org>
Wed, 28 Nov 2007 08:28:26 +0000 (00:28 -0800)
committerWayne Davison <wayned@samba.org>
Wed, 28 Nov 2007 08:28:26 +0000 (00:28 -0800)
errcode.h
log.c
main.c
options.c
rsync.yo
socket.c

index c5259d4..f9e6357 100644 (file)
--- a/errcode.h
+++ b/errcode.h
@@ -45,6 +45,7 @@
 #define RERR_DEL_LIMIT  25      /* skipped some deletes due to --max-delete */
 
 #define RERR_TIMEOUT    30      /* timeout in data send/receive */
 #define RERR_DEL_LIMIT  25      /* skipped some deletes due to --max-delete */
 
 #define RERR_TIMEOUT    30      /* timeout in data send/receive */
+#define RERR_CONTIMEOUT 35      /* timeout waiting for daemon connection */
 
 /* Although it doesn't seem to be specified anywhere,
  * ssh and the shell seem to return these values:
 
 /* Although it doesn't seem to be specified anywhere,
  * ssh and the shell seem to return these values:
diff --git a/log.c b/log.c
index fc4b583..146c082 100644 (file)
--- a/log.c
+++ b/log.c
@@ -86,6 +86,7 @@ struct {
        { RERR_PARTIAL    , "some files could not be transferred" },
        { RERR_VANISHED   , "some files vanished before they could be transferred" },
        { RERR_TIMEOUT    , "timeout in data send/receive" },
        { RERR_PARTIAL    , "some files could not be transferred" },
        { RERR_VANISHED   , "some files vanished before they could be transferred" },
        { RERR_TIMEOUT    , "timeout in data send/receive" },
+       { RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
        { RERR_CMD_FAILED , "remote shell failed" },
        { RERR_CMD_KILLED , "remote shell killed" },
        { RERR_CMD_RUN    , "remote command could not be run" },
        { RERR_CMD_FAILED , "remote shell failed" },
        { RERR_CMD_KILLED , "remote shell killed" },
        { RERR_CMD_RUN    , "remote command could not be run" },
diff --git a/main.c b/main.c
index 4c040b9..8ca164b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -63,6 +63,7 @@ extern int read_batch;
 extern int write_batch;
 extern int batch_fd;
 extern int filesfrom_fd;
 extern int write_batch;
 extern int batch_fd;
 extern int filesfrom_fd;
+extern int connect_timeout;
 extern pid_t cleanup_child_pid;
 extern struct stats stats;
 extern char *filesfrom_host;
 extern pid_t cleanup_child_pid;
 extern struct stats stats;
 extern char *filesfrom_host;
@@ -1264,6 +1265,12 @@ static int start_client(int argc, char *argv[])
                exit_cleanup(RERR_SYNTAX);
        }
 
                exit_cleanup(RERR_SYNTAX);
        }
 
+       if (connect_timeout) {
+               rprintf(FERROR, "The --contimeout option may only be "
+                               "used when connecting to an rsync daemon.\n");
+               exit_cleanup(RERR_SYNTAX);
+       }
+
        if (shell_machine) {
                p = strrchr(shell_machine,'@');
                if (p) {
        if (shell_machine) {
                p = strrchr(shell_machine,'@');
                if (p) {
index 783ca59..a3ea1c6 100644 (file)
--- a/options.c
+++ b/options.c
@@ -99,6 +99,7 @@ int xfer_dirs = -1;
 int am_daemon = 0;
 int do_stats = 0;
 int do_progress = 0;
 int am_daemon = 0;
 int do_stats = 0;
 int do_progress = 0;
+int connect_timeout = 0;
 int keep_partial = 0;
 int safe_symlinks = 0;
 int copy_unsafe_links = 0;
 int keep_partial = 0;
 int safe_symlinks = 0;
 int copy_unsafe_links = 0;
@@ -377,7 +378,8 @@ void usage(enum logcode F)
   rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
   rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
   rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
   rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
-  rprintf(F,"     --timeout=TIME          set I/O timeout in seconds\n");
+  rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
+  rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
   rprintf(F,"     --size-only             skip files that match in size\n");
   rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
   rprintf(F,"     --size-only             skip files that match in size\n");
   rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
@@ -603,6 +605,7 @@ static struct poptOption long_options[] = {
   {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
   {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
   {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
   {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
+  {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
index ec8654f..87652d4 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -378,7 +378,8 @@ to the detailed description below for a complete description.  verb(
      --delay-updates         put all updated files into place at end
  -m, --prune-empty-dirs      prune empty directory chains from file-list
      --numeric-ids           don't map uid/gid values by user/group name
      --delay-updates         put all updated files into place at end
  -m, --prune-empty-dirs      prune empty directory chains from file-list
      --numeric-ids           don't map uid/gid values by user/group name
-     --timeout=TIME          set I/O timeout in seconds
+     --timeout=SECONDS       set I/O timeout in seconds
+     --contimeout=SECONDS    set daemon connection timeout in seconds
  -I, --ignore-times          don't skip files that match size and time
      --size-only             skip files that match in size
      --modify-window=NUM     compare mod-times with reduced accuracy
  -I, --ignore-times          don't skip files that match size and time
      --size-only             skip files that match in size
      --modify-window=NUM     compare mod-times with reduced accuracy
@@ -1582,6 +1583,10 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
 timeout in seconds. If no data is transferred for the specified time
 then rsync will exit. The default is 0, which means no timeout.
 
 timeout in seconds. If no data is transferred for the specified time
 then rsync will exit. The default is 0, which means no timeout.
 
+dit(bf(--contimeout)) This option allows you to set the amount of time
+that rsync will wait for its connection to an rsync daemon to succeed.
+If the timeout is reached, rsync exits with an error.
+
 dit(bf(--address)) By default rsync will bind to the wildcard address when
 connecting to an rsync daemon.  The bf(--address) option allows you to
 specify a specific IP address (or hostname) to bind to.  See also this
 dit(bf(--address)) By default rsync will bind to the wildcard address when
 connecting to an rsync daemon.  The bf(--address) option allows you to
 specify a specific IP address (or hostname) to bind to.  See also this
@@ -2775,6 +2780,7 @@ dit(bf(23)) Partial transfer due to error
 dit(bf(24)) Partial transfer due to vanished source files
 dit(bf(25)) The --max-delete limit stopped deletions
 dit(bf(30)) Timeout in data send/receive
 dit(bf(24)) Partial transfer due to vanished source files
 dit(bf(25)) The --max-delete limit stopped deletions
 dit(bf(30)) Timeout in data send/receive
+dit(bf(35)) Timeout waiting for daemon connection
 enddit()
 
 manpagesection(ENVIRONMENT VARIABLES)
 enddit()
 
 manpagesection(ENVIRONMENT VARIABLES)
index 6bedc99..89f285a 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -32,6 +32,7 @@
 
 extern char *bind_address;
 extern int default_af_hint;
 
 extern char *bind_address;
 extern int default_af_hint;
+extern int connect_timeout;
 
 #ifdef HAVE_SIGACTION
 static struct sigaction sigact;
 
 #ifdef HAVE_SIGACTION
 static struct sigaction sigact;
@@ -157,6 +158,11 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
        return -1;
 }
 
        return -1;
 }
 
+/* connect() timeout handler based on alarm() */
+static RETSIGTYPE contimeout_handler(UNUSED(int val))
+{
+       connect_timeout = -1;
+}
 
 /**
  * Open a socket to a tcp remote host with the specified port .
 
 /**
  * Open a socket to a tcp remote host with the specified port .
@@ -261,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr,
                        s = -1;
                        continue;
                }
                        s = -1;
                        continue;
                }
-               if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+               if (connect_timeout > 0) {
+                       SIGACTION(SIGALRM, contimeout_handler);
+                       alarm(connect_timeout);
+               }
+
+               while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+                       if (connect_timeout < 0)
+                               exit_cleanup(RERR_CONTIMEOUT);
+                       if (errno == EINTR)
+                               continue;
                        close(s);
                        s = -1;
                        close(s);
                        s = -1;
-                       continue;
+                       break;
                }
                }
+
+               if (connect_timeout > 0)
+                       alarm(0);
+
+               if (s < 0)
+                       continue;
+
                if (proxied
                 && establish_proxy_connection(s, host, port,
                                               proxy_user, proxy_pass) != 0) {
                if (proxied
                 && establish_proxy_connection(s, host, port,
                                               proxy_user, proxy_pass) != 0) {