Commit 19b27a48 authored by Andrew Tridgell's avatar Andrew Tridgell

improved error handling again. Now we report messages for the remote

shell failing and propogate errors in a better fashion
parent ff81e809
...@@ -33,6 +33,7 @@ static struct map_struct *cleanup_buf; ...@@ -33,6 +33,7 @@ static struct map_struct *cleanup_buf;
static int cleanup_pid = 0; static int cleanup_pid = 0;
extern int io_error; extern int io_error;
pid_t cleanup_child_pid = -1;
/* /*
* Code is one of the RERR_* codes from errcode.h. * Code is one of the RERR_* codes from errcode.h.
...@@ -42,11 +43,17 @@ void _exit_cleanup(int code, const char *file, int line) ...@@ -42,11 +43,17 @@ void _exit_cleanup(int code, const char *file, int line)
extern int keep_partial; extern int keep_partial;
extern int log_got_error; extern int log_got_error;
if (code == 0 && io_error) code = RERR_FILEIO;
signal(SIGUSR1, SIG_IGN); signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, 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) { if (cleanup_got_literal && cleanup_fname && keep_partial) {
char *fname = cleanup_fname; char *fname = cleanup_fname;
cleanup_fname = NULL; cleanup_fname = NULL;
...@@ -68,14 +75,12 @@ void _exit_cleanup(int code, const char *file, int line) ...@@ -68,14 +75,12 @@ void _exit_cleanup(int code, const char *file, int line)
} }
} }
if (code) log_exit(code, file, line); if (code == 0 && (io_error || log_got_error)) {
code = RERR_PARTIAL;
if (code == 0) {
if (log_got_error) {
code = RERR_FILEIO;
}
} }
if (code) log_exit(code, file, line);
exit(code); exit(code);
} }
......
...@@ -36,5 +36,22 @@ ...@@ -36,5 +36,22 @@
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */ #define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */ #define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */ #define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_PARTIAL 23 /* partial transfer */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */ #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
...@@ -40,7 +40,7 @@ struct { ...@@ -40,7 +40,7 @@ struct {
{ RERR_SYNTAX , "syntax or usage error" }, { RERR_SYNTAX , "syntax or usage error" },
{ RERR_PROTOCOL , "protocol incompatibility" }, { RERR_PROTOCOL , "protocol incompatibility" },
{ RERR_FILESELECT , "errors selecting input/output files, dirs" }, { 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_SOCKETIO , "error in socket IO" },
{ RERR_FILEIO , "error in file IO" }, { RERR_FILEIO , "error in file IO" },
{ RERR_STREAMIO , "error in rsync protocol data stream" }, { RERR_STREAMIO , "error in rsync protocol data stream" },
...@@ -49,7 +49,12 @@ struct { ...@@ -49,7 +49,12 @@ struct {
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" }, { RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
{ RERR_WAITCHILD , "some error returned by waitpid()" }, { RERR_WAITCHILD , "some error returned by waitpid()" },
{ RERR_MALLOC , "error allocating core memory buffers" }, { RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "partial transfer" },
{ RERR_TIMEOUT , "timeout in data send/receive" }, { 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 } { 0, NULL }
}; };
...@@ -506,7 +511,7 @@ void log_exit(int code, const char *file, int line) ...@@ -506,7 +511,7 @@ void log_exit(int code, const char *file, int line)
if (!name) if (!name)
name = "unexplained error"; 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); name, code, file, line);
} }
} }
......
...@@ -126,23 +126,11 @@ static void report(int f) ...@@ -126,23 +126,11 @@ static void report(int f)
/* Start the remote shell. cmd may be NULL to use the default. */ /* 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 static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
* 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)
{ {
char *args[100]; char *args[100];
int i,argc=0, ret; int i,argc=0;
pid_t ret;
char *tok,*dir=NULL; char *tok,*dir=NULL;
extern int local_server; extern int local_server;
extern char *rsync_path; extern char *rsync_path;
...@@ -484,13 +472,16 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) ...@@ -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 * This is called once the connection has been negotiated. It is used
* for rsyncd, remote-shell, and local connections. * 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; struct file_list *flist;
int status = 0, status2 = 0; int status = 0, status2 = 0;
char *local_name = NULL; char *local_name = NULL;
extern int am_sender; extern int am_sender;
extern int remote_version; extern int remote_version;
extern pid_t cleanup_child_pid;
cleanup_child_pid = pid;
set_nonblocking(f_in); set_nonblocking(f_in);
set_nonblocking(f_out); set_nonblocking(f_out);
...@@ -583,7 +574,8 @@ static int start_client(int argc, char *argv[]) ...@@ -583,7 +574,8 @@ static int start_client(int argc, char *argv[])
char *shell_machine = NULL; char *shell_machine = NULL;
char *shell_path = NULL; char *shell_path = NULL;
char *shell_user = NULL; char *shell_user = NULL;
int pid, ret; int ret;
pid_t pid;
int f_in,f_out; int f_in,f_out;
extern int local_server; extern int local_server;
extern int am_sender; extern int am_sender;
...@@ -700,10 +692,13 @@ static RETSIGTYPE sigusr1_handler(int val) { ...@@ -700,10 +692,13 @@ static RETSIGTYPE sigusr1_handler(int val) {
static RETSIGTYPE sigusr2_handler(int val) { static RETSIGTYPE sigusr2_handler(int val) {
extern int log_got_error; extern int log_got_error;
if (log_got_error) _exit(RERR_FILEIO); if (log_got_error) _exit(RERR_PARTIAL);
_exit(0); _exit(0);
} }
static RETSIGTYPE sigchld_handler(int val) {
}
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
extern int am_root; extern int am_root;
...@@ -715,6 +710,7 @@ int main(int argc,char *argv[]) ...@@ -715,6 +710,7 @@ int main(int argc,char *argv[])
signal(SIGUSR1, sigusr1_handler); signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler); signal(SIGUSR2, sigusr2_handler);
signal(SIGCHLD, sigchld_handler);
starttime = time(NULL); starttime = time(NULL);
am_root = (getuid() == 0); am_root = (getuid() == 0);
......
...@@ -93,9 +93,9 @@ int fd_pair(int fd[2]) ...@@ -93,9 +93,9 @@ int fd_pair(int fd[2])
used to cope with badly broken rsh implementations like the one on used to cope with badly broken rsh implementations like the one on
solaris. 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 to_child_pipe[2];
int from_child_pipe[2]; int from_child_pipe[2];
extern int blocking_io; extern int blocking_io;
...@@ -108,7 +108,7 @@ int piped_child(char **command,int *f_in,int *f_out) ...@@ -108,7 +108,7 @@ int piped_child(char **command,int *f_in,int *f_out)
pid = do_fork(); pid = do_fork();
if (pid < 0) { if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno)); rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC); exit_cleanup(RERR_IPC);
} }
...@@ -148,9 +148,9 @@ int piped_child(char **command,int *f_in,int *f_out) ...@@ -148,9 +148,9 @@ int piped_child(char **command,int *f_in,int *f_out)
return pid; 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 to_child_pipe[2];
int from_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) ...@@ -162,7 +162,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
pid = do_fork(); pid = do_fork();
if (pid < 0) { if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno)); rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC); exit_cleanup(RERR_IPC);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment