-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcatch_crash_signals.diff
138 lines (130 loc) · 4.46 KB
/
catch_crash_signals.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
Igor Yu. Zhbanov wrote:
> I am using rsync compiled with Cygwin on windows.
> I must call rsync from the *.bat script (I don't want to use a bash on Windows)
> and I have noticed that in the case when program compiled by Cygwin crashes
> via segmentation fault and default SIGSEGV handler is called, then it
> terminates process with exit status 0 as I see it from my *.bat script.
> (But if I invoke a program from bash (compiled with Cygwin too) I will see
> error code 139 as expected.)
>
> It is a Cygwin's problem, not an rsync's, but to use it on windows and
> to distinguish situations when rsync crashes and when it exits normally,
> I have written signal handler which terminates process with code 50.
> You may use conventional 139. Also signal handler writes corresponding
> message to log file.
>
> By the way. When I terminate rsync in daemon mode by pressing Control-C,
> it writes an error to log. May be this is not an error but info or notice?
I'm not sure I like this, but if you run into the cygwin problem, this might
prove helpful.
To use this patch, run these commands for a successful build:
patch -p1 <patches/catch_crash_signals.diff
./configure (optional if already run)
make
based-on: 6c8ca91c731b7bf2b081694bda85b7dadc2b7aff
diff --git a/errcode.h b/errcode.h
--- a/errcode.h
+++ b/errcode.h
@@ -47,6 +47,8 @@
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
+#define RERR_WECRASHED 50 /* We have crashed. */
+
/* 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
--- a/log.c
+++ b/log.c
@@ -92,6 +92,7 @@ struct {
{ RERR_TERMINATED , "sibling process terminated abnormally" },
{ RERR_SIGNAL1 , "received SIGUSR1" },
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
+ { RERR_WECRASHED , "rsync caught a CRASH-causing signal" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files/attrs were not transferred (see previous errors)" },
diff --git a/main.c b/main.c
--- a/main.c
+++ b/main.c
@@ -218,8 +218,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
*exit_code_ptr = RERR_TERMINATED;
else
*exit_code_ptr = RERR_WAITCHILD;
- } else
+ } else {
*exit_code_ptr = WEXITSTATUS(status);
+ if (*exit_code_ptr == RERR_WECRASHED)
+ *exit_code_ptr = RERR_CRASHED;
+ }
}
void write_del_stats(int f)
@@ -1637,6 +1640,14 @@ void remember_children(UNUSED(int val))
break;
}
}
+ if (WIFSIGNALED(status)) {
+ rprintf(FLOG,
+ "rsync error: (1) Child proccess has unexpectedly died with signal %d\n",
+ WTERMSIG(status));
+ } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) {
+ rprintf(FLOG,
+ "rsync error: (1) Child proccess has CRASHED.\n");
+ }
}
#endif
#ifndef HAVE_SIGACTION
@@ -1690,6 +1701,13 @@ static void rsync_panic_handler(UNUSED(int whatsig))
}
#endif
+static void rsync_crash_handler(UNUSED(int whatsig))
+{
+ log_exit(RERR_WECRASHED, __FILE__, __LINE__);
+ logfile_close();
+ _exit(RERR_WECRASHED);
+}
+
static void unset_env_var(const char *var)
{
#ifdef HAVE_UNSETENV
@@ -1706,7 +1724,6 @@ static void unset_env_var(const char *var)
#endif
}
-
int main(int argc,char *argv[])
{
int ret;
@@ -1730,6 +1747,11 @@ int main(int argc,char *argv[])
SIGACTMASK(SIGFPE, rsync_panic_handler);
SIGACTMASK(SIGABRT, rsync_panic_handler);
SIGACTMASK(SIGBUS, rsync_panic_handler);
+#else
+ SIGACTMASK(SIGSEGV, rsync_crash_handler);
+ SIGACTMASK(SIGFPE, rsync_crash_handler);
+ SIGACTMASK(SIGABRT, rsync_crash_handler);
+ SIGACTMASK(SIGBUS, rsync_crash_handler);
#endif
#ifdef SIGINFO
SIGACTMASK(SIGINFO, siginfo_handler);
diff --git a/socket.c b/socket.c
--- a/socket.c
+++ b/socket.c
@@ -522,7 +522,17 @@ int is_a_socket(int fd)
static void sigchld_handler(UNUSED(int val))
{
#ifdef WNOHANG
- while (waitpid(-1, NULL, WNOHANG) > 0) {}
+ int status;
+ while (waitpid(-1, &status, WNOHANG) > 0) {
+ if (WIFSIGNALED(status)) {
+ rprintf(FLOG,
+ "rsync error: (3) Child proccess has unexpectedly died with signal %d\n",
+ WTERMSIG(status));
+ } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) {
+ rprintf(FLOG,
+ "rsync error: (3) Child proccess has CRASHED.\n");
+ }
+ }
#endif
#ifndef HAVE_SIGACTION
signal(SIGCHLD, sigchld_handler);