summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-03-23 01:26:04 +0000
committerAndrew Tridgell <tridge@samba.org>2001-03-23 01:26:04 +0000
commit19b27a485e833e08160ef0bae8f604c6f60e5ef8 (patch)
treec9a231fcdecd11884aacbc2dbf93262e5c5ad8de
parentff81e809f46293171a332a2faa320aca57277b4b (diff)
downloadrsync-19b27a485e833e08160ef0bae8f604c6f60e5ef8.tar.gz
improved error handling again. Now we report messages for the remote
shell failing and propogate errors in a better fashion
-rw-r--r--cleanup.c21
-rw-r--r--errcode.h17
-rw-r--r--log.c9
-rw-r--r--main.c32
-rw-r--r--util.c12
5 files changed, 57 insertions, 34 deletions
diff --git a/cleanup.c b/cleanup.c
index 4b9cad3a..480c2009 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -33,6 +33,7 @@ static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
extern int io_error;
+pid_t cleanup_child_pid = -1;
/*
* Code is one of the RERR_* codes from errcode.h.
@@ -42,11 +43,17 @@ void _exit_cleanup(int code, const char *file, int line)
extern int keep_partial;
extern int log_got_error;
- if (code == 0 && io_error) code = RERR_FILEIO;
-
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
+ if (cleanup_child_pid != -1) {
+ int status;
+ if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
+ status = WEXITSTATUS(status);
+ if (status > code) code = status;
+ }
+ }
+
if (cleanup_got_literal && cleanup_fname && keep_partial) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
@@ -68,14 +75,12 @@ void _exit_cleanup(int code, const char *file, int line)
}
}
- if (code) log_exit(code, file, line);
-
- if (code == 0) {
- if (log_got_error) {
- code = RERR_FILEIO;
- }
+ if (code == 0 && (io_error || log_got_error)) {
+ code = RERR_PARTIAL;
}
+ if (code) log_exit(code, file, line);
+
exit(code);
}
diff --git a/errcode.h b/errcode.h
index 997e2d22..fc1eca78 100644
--- a/errcode.h
+++ b/errcode.h
@@ -36,5 +36,22 @@
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
+#define RERR_PARTIAL 23 /* partial transfer */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
+
+/* Although it doesn't seem to be specified anywhere,
+ * ssh and the shell seem to return these values:
+ *
+ * 124 if the command exited with status 255
+ * 125 if the command is killed by a signal
+ * 126 if the command cannot be run
+ * 127 if the command is not found
+ *
+ * and we could use this to give a better explanation if the remote
+ * command is not found.
+ */
+#define RERR_CMD_FAILED 124
+#define RERR_CMD_KILLED 125
+#define RERR_CMD_RUN 126
+#define RERR_CMD_NOTFOUND 127
diff --git a/log.c b/log.c
index 492948bd..e67477b7 100644
--- a/log.c
+++ b/log.c
@@ -40,7 +40,7 @@ struct {
{ RERR_SYNTAX , "syntax or usage error" },
{ RERR_PROTOCOL , "protocol incompatibility" },
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
- { RERR_UNSUPPORTED , "requested action not supported" },
+ { RERR_UNSUPPORTED, "requested action not supported" },
{ RERR_SOCKETIO , "error in socket IO" },
{ RERR_FILEIO , "error in file IO" },
{ RERR_STREAMIO , "error in rsync protocol data stream" },
@@ -49,7 +49,12 @@ struct {
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
{ RERR_WAITCHILD , "some error returned by waitpid()" },
{ RERR_MALLOC , "error allocating core memory buffers" },
+ { RERR_PARTIAL , "partial transfer" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
+ { RERR_CMD_FAILED , "remote shell failed" },
+ { RERR_CMD_KILLED , "remote shell killed" },
+ { RERR_CMD_RUN, "remote command could not be run" },
+ { RERR_CMD_NOTFOUND, "remote command not found" },
{ 0, NULL }
};
@@ -506,7 +511,7 @@ void log_exit(int code, const char *file, int line)
if (!name)
name = "unexplained error";
- rprintf(FLOG,"transfer interrupted: %s (code %d) at %s(%d)\n",
+ rprintf(FERROR,"transfer error: %s (code %d) at %s(%d)\n",
name, code, file, line);
}
}
diff --git a/main.c b/main.c
index dae6e790..f696474c 100644
--- a/main.c
+++ b/main.c
@@ -126,23 +126,11 @@ static void report(int f)
/* Start the remote shell. cmd may be NULL to use the default. */
-/* TODO: When the shell exits, look at its return value, as this may
- * well tell us if something went wrong in trying to connect to the
- * remote machine. Although it doesn't seem to be specified anywhere,
- * ssh and the shell seem to return these values:
- *
- * 124 if the command exited with status 255
- * 125 if the command is killed by a signal
- * 126 if the command cannot be run
- * 127 if the command is not found
- *
- * and we could use this to give a better explanation if the remote
- * command is not found.
- */
-static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
+static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
{
char *args[100];
- int i,argc=0, ret;
+ int i,argc=0;
+ pid_t ret;
char *tok,*dir=NULL;
extern int local_server;
extern char *rsync_path;
@@ -484,13 +472,16 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
* This is called once the connection has been negotiated. It is used
* for rsyncd, remote-shell, and local connections.
*/
-int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
+int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
{
struct file_list *flist;
int status = 0, status2 = 0;
char *local_name = NULL;
extern int am_sender;
extern int remote_version;
+ extern pid_t cleanup_child_pid;
+
+ cleanup_child_pid = pid;
set_nonblocking(f_in);
set_nonblocking(f_out);
@@ -583,7 +574,8 @@ static int start_client(int argc, char *argv[])
char *shell_machine = NULL;
char *shell_path = NULL;
char *shell_user = NULL;
- int pid, ret;
+ int ret;
+ pid_t pid;
int f_in,f_out;
extern int local_server;
extern int am_sender;
@@ -700,10 +692,13 @@ static RETSIGTYPE sigusr1_handler(int val) {
static RETSIGTYPE sigusr2_handler(int val) {
extern int log_got_error;
- if (log_got_error) _exit(RERR_FILEIO);
+ if (log_got_error) _exit(RERR_PARTIAL);
_exit(0);
}
+static RETSIGTYPE sigchld_handler(int val) {
+}
+
int main(int argc,char *argv[])
{
extern int am_root;
@@ -715,6 +710,7 @@ int main(int argc,char *argv[])
signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler);
+ signal(SIGCHLD, sigchld_handler);
starttime = time(NULL);
am_root = (getuid() == 0);
diff --git a/util.c b/util.c
index 48935cc4..d917f07b 100644
--- a/util.c
+++ b/util.c
@@ -93,9 +93,9 @@ int fd_pair(int fd[2])
used to cope with badly broken rsh implementations like the one on
solaris.
*/
-int piped_child(char **command,int *f_in,int *f_out)
+pid_t piped_child(char **command,int *f_in,int *f_out)
{
- int pid;
+ pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
extern int blocking_io;
@@ -108,7 +108,7 @@ int piped_child(char **command,int *f_in,int *f_out)
pid = do_fork();
- if (pid < 0) {
+ if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -148,9 +148,9 @@ int piped_child(char **command,int *f_in,int *f_out)
return pid;
}
-int local_child(int argc, char **argv,int *f_in,int *f_out)
+pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
{
- int pid;
+ pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
@@ -162,7 +162,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
pid = do_fork();
- if (pid < 0) {
+ if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}