From 19b27a485e833e08160ef0bae8f604c6f60e5ef8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 Mar 2001 01:26:04 +0000 Subject: [PATCH] improved error handling again. Now we report messages for the remote shell failing and propogate errors in a better fashion --- cleanup.c | 21 +++++++++++++-------- errcode.h | 17 +++++++++++++++++ log.c | 9 +++++++-- main.c | 32 ++++++++++++++------------------ util.c | 12 ++++++------ 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); } -- 2.34.1