我正在阅读APUE,第10章。这是我的代码。
#include "apue.h"
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;
int
main(void)
{
if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if(signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
//print signal.
pr_mask("Starting main: ");
if(sigsetjmp(jmpbuf, 1)) {
pr_mask("End main: ");
exit(0);
}
canjmp = 1;
for(;;)
pause();
}
static void
sig_usr1(int signo)
{
time_t starttime;
if(canjmp == 0) {
return;
}
pr_mask("starting sig_usr1: ");
alarm(3);
starttime = time(NULL);
for(;;)
if(time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: ");
canjmp = 0;
siglongjmp(jmpbuf, 1);
}
static void
sig_alrm(int signo)
{
pr_mask("in sig_arlm: ");
}
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("\n");
errno = errno_save;
}
我认为输出会是这样的:
Starting main:
starting sig_usr1: SIGUSR1
in sig_alrm: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
End main:
但似乎有些不对劲,这实际上是我的输出:
Starting main:
starting sig_usr1:
in sig_alrm:
finishing sig_usr1:
End main:
这不是信号。请帮帮我。
答案 0 :(得分:1)
我认为问题可能是您使用signal()
而不是sigaction()
来设置信号处理。并且signal()
不会屏蔽任何其他信号 - 因此没有信号显示为被阻止。我修改了您的代码,如下所示,根据是否有任何参数使用signal()
和sigaction()
。
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef void (*Handler)(int);
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;
static void pr_mask(const char *str);
static void err_sys(const char *str)
{
int errnum = errno;
fprintf(stderr, "%s (%d: %s)\n", str, errnum, strerror(errnum));
exit(1);
}
static void set_sigaction(int signum, Handler handler)
{
struct sigaction nact;
nact.sa_handler = handler;
sigfillset(&nact.sa_mask);
//sigemptyset(&nact.sa_mask);
nact.sa_flags = 0;
if (sigaction(signum, &nact, 0) != 0)
err_sys("Failed to set signal handling");
}
int
main(int argc, char **argv)
{
printf("PID = %u\n", (unsigned)getpid());
if (argc > 1)
{
if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
}
else
{
set_sigaction(SIGUSR1, sig_usr1);
set_sigaction(SIGALRM, sig_alrm);
}
//print signal.
pr_mask("Starting main: ");
if (sigsetjmp(jmpbuf, 1)) {
pr_mask("End main: ");
exit(0);
}
canjmp = 1;
for (;;)
pause();
}
static void
sig_usr1(int signo)
{
time_t starttime;
if (canjmp == 0) {
return;
}
pr_mask("starting sig_usr1: ");
alarm(3);
starttime = time(NULL);
for (;;)
if (time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: ");
canjmp = 0;
siglongjmp(jmpbuf, 1);
}
static void
sig_alrm(int signo)
{
pr_mask("in sig_arlm: ");
}
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("\n");
errno = errno_save;
}
使用当前的XCode(4.2?)在MacOS X 10.7.2上运行,我得到(例如):
$ ./sigtest
PID = 11066
Starting main:
starting sig_usr1: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1 SIGALRM
in sig_arlm: SIGUSR1 SIGALRM
End main:
$ ./sigtest 1
PID = 11067
Starting main:
starting sig_usr1: SIGUSR1
in sig_arlm: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
End main:
$