Commit | Line | Data |
---|---|---|
ae5c7864 WD |
1 | Igor Yu. Zhbanov wrote: |
2 | > I am using rsync compiled with Cygwin on windows. | |
3 | > I must call rsync from the *.bat script (I don't want to use a bash on Windows) | |
4 | > and I have noticed that in the case when program compiled by Cygwin crashes | |
5 | > via segmentation fault and default SIGSEGV handler is called, then it | |
6 | > terminates process with exit status 0 as I see it from my *.bat script. | |
7 | > (But if I invoke a program from bash (compiled with Cygwin too) I will see | |
8 | > error code 139 as expected.) | |
9 | > | |
10 | > It is a Cygwin's problem, not an rsync's, but to use it on windows and | |
11 | > to distinguish situations when rsync crashes and when it exits normally, | |
12 | > I have written signal handler which terminates process with code 50. | |
13 | > You may use conventional 139. Also signal handler writes corresponding | |
14 | > message to log file. | |
15 | > | |
16 | > By the way. When I terminate rsync in daemon mode by pressing Control-C, | |
17 | > it writes an error to log. May be this is not an error but info or notice? | |
18 | ||
19 | I'm not sure I like this, but if you run into the cygwin problem, this might | |
20 | prove helpful. | |
21 | ||
03019e41 WD |
22 | To use this patch, run these commands for a successful build: |
23 | ||
24 | patch -p1 <patches/catch_crash_signals.diff | |
25 | ./configure (optional if already run) | |
26 | make | |
27 | ||
ae5c7864 WD |
28 | --- old/errcode.h |
29 | +++ new/errcode.h | |
30 | @@ -47,6 +47,8 @@ | |
31 | ||
32 | #define RERR_TIMEOUT 30 /* timeout in data send/receive */ | |
33 | ||
34 | +#define RERR_WECRASHED 50 /* We have crashed. */ | |
35 | + | |
36 | /* Although it doesn't seem to be specified anywhere, | |
37 | * ssh and the shell seem to return these values: | |
38 | * | |
39 | --- old/log.c | |
40 | +++ new/log.c | |
41 | @@ -77,6 +77,7 @@ struct { | |
42 | { RERR_TERMINATED , "sibling process terminated abnormally" }, | |
43 | { RERR_SIGNAL1 , "received SIGUSR1" }, | |
44 | { RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" }, | |
45 | + { RERR_WECRASHED , "rsync caught a CRASH-causing signal" }, | |
46 | { RERR_WAITCHILD , "waitpid() failed" }, | |
47 | { RERR_MALLOC , "error allocating core memory buffers" }, | |
48 | { RERR_PARTIAL , "some files could not be transferred" }, | |
49 | --- old/main.c | |
50 | +++ new/main.c | |
03019e41 | 51 | @@ -149,8 +149,11 @@ static void wait_process_with_flush(pid_ |
ae5c7864 WD |
52 | *exit_code_ptr = RERR_TERMINATED; |
53 | else | |
54 | *exit_code_ptr = RERR_WAITCHILD; | |
55 | - } else | |
56 | + } else { | |
57 | *exit_code_ptr = WEXITSTATUS(status); | |
58 | + if (*exit_code_ptr == RERR_WECRASHED) | |
59 | + *exit_code_ptr = RERR_CRASHED; | |
60 | + } | |
61 | } | |
62 | ||
63 | /* This function gets called from all 3 processes. We want the client side | |
03019e41 | 64 | @@ -1211,6 +1214,14 @@ RETSIGTYPE remember_children(UNUSED(int |
ae5c7864 WD |
65 | break; |
66 | } | |
67 | } | |
68 | + if (WIFSIGNALED(status)) { | |
69 | + rprintf(FLOG, | |
70 | + "rsync error: (1) Child proccess has unexpectedly died with signal %d\n", | |
71 | + WTERMSIG(status)); | |
72 | + } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) { | |
73 | + rprintf(FLOG, | |
74 | + "rsync error: (1) Child proccess has CRASHED.\n"); | |
75 | + } | |
76 | } | |
77 | #endif | |
78 | #ifndef HAVE_SIGACTION | |
03019e41 | 79 | @@ -1269,6 +1280,12 @@ static RETSIGTYPE rsync_panic_handler(UN |
ae5c7864 WD |
80 | } |
81 | #endif | |
82 | ||
83 | +static RETSIGTYPE rsync_crash_handler(UNUSED(int whatsig)) | |
84 | +{ | |
85 | + log_exit(RERR_WECRASHED, __FILE__, __LINE__); | |
86 | + logfile_close(); | |
87 | + _exit(RERR_WECRASHED); | |
88 | +} | |
89 | ||
90 | int main(int argc,char *argv[]) | |
91 | { | |
03019e41 | 92 | @@ -1291,6 +1308,11 @@ int main(int argc,char *argv[]) |
ae5c7864 WD |
93 | SIGACTMASK(SIGFPE, rsync_panic_handler); |
94 | SIGACTMASK(SIGABRT, rsync_panic_handler); | |
95 | SIGACTMASK(SIGBUS, rsync_panic_handler); | |
96 | +#else | |
97 | + SIGACTMASK(SIGSEGV, rsync_crash_handler); | |
98 | + SIGACTMASK(SIGFPE, rsync_crash_handler); | |
99 | + SIGACTMASK(SIGABRT, rsync_crash_handler); | |
100 | + SIGACTMASK(SIGBUS, rsync_crash_handler); | |
101 | #endif | |
102 | ||
103 | starttime = time(NULL); | |
104 | --- old/socket.c | |
105 | +++ new/socket.c | |
03019e41 | 106 | @@ -454,7 +454,17 @@ int is_a_socket(int fd) |
ae5c7864 WD |
107 | static RETSIGTYPE sigchld_handler(UNUSED(int val)) |
108 | { | |
109 | #ifdef WNOHANG | |
110 | - while (waitpid(-1, NULL, WNOHANG) > 0) {} | |
111 | + int status; | |
112 | + while (waitpid(-1, &status, WNOHANG) > 0) { | |
113 | + if (WIFSIGNALED(status)) { | |
114 | + rprintf(FLOG, | |
115 | + "rsync error: (3) Child proccess has unexpectedly died with signal %d\n", | |
116 | + WTERMSIG(status)); | |
117 | + } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) { | |
118 | + rprintf(FLOG, | |
119 | + "rsync error: (3) Child proccess has CRASHED.\n"); | |
120 | + } | |
121 | + } | |
122 | #endif | |
123 | #ifndef HAVE_SIGACTION | |
124 | signal(SIGCHLD, sigchld_handler); |