測試證明代碼: 操作說明,這裡我給出我和作者交流時的說明,所以用的是英文,不過我英文水平有限,希望諒解: I should give you my manipulation. You should send a SIGUSR1 to the process in less than 20 secon ...
測試證明代碼:
#include <unistd.h> #include <fcntl.h> #include <time.h> #include "apue.h" static void sig_alrm(int signo) { /* nothing to do, just returning wakes up sigsuspend */ } static void sig_usr1(int signo) { } //static void sig_alrm_test(int signo) //{ // err_msg("left an alrm"); //} unsigned int sleep(unsigned int seconds) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; timespec ts; // ++ ts.tv_sec = 25; // ++ ts.tv_nsec = 0; // ++ /* set our handler, save previous information */ newact.sa_handler = sig_alrm; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); /* block SIGALRM and save current signal mask */ sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); alarm(seconds); suspmask = oldmask; /* make sure SIGALRM isn't block */ sigdelset(&suspmask, SIGALRM); /* wait for any signal to be caught */ sigsuspend(&suspmask); nanosleep(&ts, NULL); // ++ /* some signal has been caught, SIGALRM is now blocked */ unslept = alarm(0); /* reset previous action */ sigaction(SIGALRM, &oldact, NULL); /* reset signal mask, which unblocks SIGALRM */ sigprocmask(SIG_SETMASK, &oldmask, NULL); return unslept; } int main(int argc, char *argv[]) { struct sigaction useract; struct sigaction alrmact; useract.sa_handler = sig_usr1; sigemptyset(&useract.sa_mask); useract.sa_flags = 0; if (sigaction(SIGUSR1, &useract, NULL) < 0) err_sys("SIG SUR1 error"); // alrmact.sa_handler = sig_alrm_test; // sigemptyset(&alrmact.sa_mask); // alrmact.sa_flags = 0; // if (sigaction(SIGALRM, &alrmact, NULL) < 0) // err_sys("SIG ALRM error"); sleep(20); return 0; }
操作說明,這裡我給出我和作者交流時的說明,所以用的是英文,不過我英文水平有限,希望諒解:
I should give you my manipulation. You should send a SIGUSR1 to the process in less than 20 seconds. So that when alarm(0) tries to cancel the alarm, it was not expired. You see, I didn't send the process SIGALARM, but the SIGALARM handler was fired.
下麵是運行時候的結果(為了讓作者可以看清楚,使用的是英文):
下麵是作者的回覆(中間有一些曲折,給出最後的部分回覆內容):
Yes, there is a very small window where if the sigsuspend() is interrupted by a different signal and the SIGALRM is posted before calling alarm(0) to cancel it, that the process will be terminated if the default disposition of SIGALRM is in effect. You have artificially widened that window by adding the call to nanosleep().