summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--errcode.h1
-rw-r--r--log.c1
-rw-r--r--main.c7
-rw-r--r--options.c5
-rw-r--r--rsync.yo8
-rw-r--r--socket.c26
6 files changed, 44 insertions, 4 deletions
diff --git a/errcode.h b/errcode.h
index c5259d41..f9e63578 100644
--- 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_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:
diff --git a/log.c b/log.c
index fc4b5833..146c082b 100644
--- 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_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" },
diff --git a/main.c b/main.c
index 4c040b99..8ca164bd 100644
--- 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 connect_timeout;
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);
}
+ 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) {
diff --git a/options.c b/options.c
index 783ca594..a3ea1c6a 100644
--- 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 connect_timeout = 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," --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");
@@ -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 },
+ {"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 },
diff --git a/rsync.yo b/rsync.yo
index ec8654f9..87652d41 100644
--- 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
- --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
@@ -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.
+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
@@ -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(35)) Timeout waiting for daemon connection
enddit()
manpagesection(ENVIRONMENT VARIABLES)
diff --git a/socket.c b/socket.c
index 6bedc991..89f285a2 100644
--- a/socket.c
+++ b/socket.c
@@ -32,6 +32,7 @@
extern char *bind_address;
extern int default_af_hint;
+extern int connect_timeout;
#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;
}
+/* 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 .
@@ -261,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr,
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;
- 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) {