diff --git a/rts.tests/supervise-stop.exp b/rts.tests/supervise-stop.exp index 906fc1c..a0cc79a 100644 --- a/rts.tests/supervise-stop.exp +++ b/rts.tests/supervise-stop.exp @@ -2,6 +2,6 @@ in stop --- supervise stops log after main -Caught CONT Caught TERM +Caught CONT diff --git a/rts.tests/svc.exp b/rts.tests/svc.exp index 71865bd..b98c28a 100644 --- a/rts.tests/svc.exp +++ b/rts.tests/svc.exp @@ -8,5 +8,5 @@ Caught QUIT Caught USR1 Caught USR2 Caught WINCH -Caught CONT Caught TERM +Caught CONT diff --git a/sleeper.c b/sleeper.c index 637ba60..081f18b 100644 --- a/sleeper.c +++ b/sleeper.c @@ -4,6 +4,9 @@ #include "str.h" #include +int flag_cont = 0; +int flag_term = 0; + static void catch_sig(int sig) { char buf[7+14+2] = "Caught "; @@ -12,11 +15,11 @@ static void catch_sig(int sig) int i; switch (sig) { case SIGALRM: name = "ALRM"; break; - case SIGCONT: name = "CONT"; break; + case SIGCONT: flag_cont = 1; return; case SIGHUP: name = "HUP"; break; case SIGINT: name = "INT"; break; case SIGQUIT: name = "QUIT"; break; - case SIGTERM: name = "TERM"; break; + case SIGTERM: flag_term = 1; return; case SIGUSR1: name = "USR1"; break; case SIGUSR2: name = "USR2"; break; case SIGWINCH: name = "WINCH"; break; @@ -27,12 +30,13 @@ static void catch_sig(int sig) i += 7; buf[i++] = '\n'; ignored = write(1,buf,i); - if (sig != SIGCONT) - _exit(1); + _exit(1); } int main(void) { + int i, ignored; + sig_catch(SIGALRM,catch_sig); sig_catch(SIGCONT,catch_sig); sig_catch(SIGHUP,catch_sig); @@ -42,6 +46,48 @@ int main(void) sig_catch(SIGUSR1,catch_sig); sig_catch(SIGUSR2,catch_sig); sig_catch(SIGWINCH,catch_sig); - sleep(9999); + + for (i = 0; i < 9999; ++i) { + if (!flag_cont && !flag_term) sleep(1); + /* + * here we have some combination of flag_cont and flag_term. + * + * if neither, nothing happened. continue. + * + * if both, then sig_term was interrupted by sig_cont, so we know + * we've handled svc -d. print both and exit. + * + * if only flag_cont set, we know we're handling svc -c since svc -d + * would've either set both (as above) or only set flag_term (below). + * print the cont message and exit. + * + * if only flag_term set, we might be handling svc -t by itself, or + * maybe svc -d has returned from the sig_term handler before sig_cont + * arrived. in either case, reset flag_term, print the term message, + * and continue. + * + * as a special case, if only flag_cont set, we might be handling + * the second half of svc -d where sig_cont arrived so late we already + * looped around here once and handled the sig_term. print the cont + * message and exit. + * + * one hidden gotcha here is that any test following a sig_term will + * be handled by the same sleeper instance as sig_term itself. don't + * schedule a svc -t test last. + * + * another gotcha is the race condition between the flag test above + * and sleep(). if a cont/term signal arrives at that point, we incur + * additional delay which could muck up the tests. don't test svc -c + * immediately after svc -t, and schedule svc -dx test last. + */ + if (flag_term) { + flag_term = 0; + ignored = write(1, "Caught TERM\n", 12); + } + if (flag_cont) { + ignored = write(1, "Caught CONT\n", 12); + _exit(1); + } + } return 0; }