当信号由操作系统传递但进程或线程阻止它时,信号处于未决状态。如果您没有阻止 SIGUSR1,那么它将被交付,并且 SIGUSR1 的默认处置是终止进程。在这种情况下,您sigpending
什么都不做;它被有效地绕过了。首先阻止 SIGUSR1pthread_sigmask
或(可选地)处理它。
总的来说,这是一个可疑的设计。使用阻塞/正在等待的代码,根据 SECONDS 设置的时间长短,您仍然可以等待很长时间,然后您的线程循环才能发现是时候关闭了。如果您真的想为此使用信号,我建议您建立一个设置开关的信号处理程序。当 SIGUSR1 被传递时,将调用处理程序,它设置开关,sleep
将被信号中断,您检查 EINTR 并立即循环检查开关,然后pthread_exit
.
选项1(在linux上编译)
#define _POSIX_C_SOURCE 2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
void* foo(void* arg)
{
sigset_t set, isSignal, allSigs;
sigfillset(&allSigs);
if (sigprocmask(SIG_SETMASK, &allSigs, NULL) == -1)
{
printf("sigprocmask: %m\n");
exit(1);
}
sigemptyset(&set);
if (sigaddset(&set, SIGUSR1) == -1)
{
printf("sigaddset: %m\n");
exit(1);
}
while (1)
{
if (sigpending(&isSignal) != 0)
{
printf("sigpending: %m\n");
exit(1);
}
else
if (sigismember(&isSignal, SIGUSR1))
{
printf("signal pending for thread, exiting\n");
break;
}
printf("Doing groovy thread stuff...\n");
sleep(2);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t tid;
int rc;
rc = pthread_create(&tid, NULL, foo, NULL);
if (rc)
{
printf("pthread_create: %m\n");
exit(1);
}
sleep(10);
pthread_kill(tid, SIGUSR1);
pthread_join(tid, NULL);
}
选项2(在linux上编译)
#define _POSIX_C_SOURCE 2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
volatile int stop = 0;
void handler(int sig)
{
stop = 1;
}
void* foo(void* arg)
{
signal(SIGUSR1, handler); //use sigaction, i'm too lazy here
while (! stop)
{
printf("Doing groovy thread stuff...\n");
if (sleep(4) > 0)
if (errno == EINTR)
{
printf("sleep interrupted, exiting thread...\n");
continue;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t tid;
int rc;
rc = pthread_create(&tid, NULL, foo, NULL);
if (rc)
{
printf("pthread_create: %m\n");
exit(1);
}
sleep(10);
pthread_kill(tid, SIGUSR1);
pthread_join(tid, NULL);
}
选项 3 如果可以,请使用其他机制。建议。