use*_*907 2 unix multithreading posix signals pthreads
我有一个非常简单的线程:它将保持活动的数据包发送到服务器,然后休眠。我希望我的主线程向线程发出退出信号,但是每当我调用 pthread_kill() 时,它似乎都会使我的进程崩溃。
我试图在我的 while 循环开始时调用 sigpending() 后跟 sigismember(),但我认为它正在崩溃,因为它不知道任何处理信号的句柄(我在之前使用 sigaddset() while 循环),如下:
void* foo(void* arg)
{
sigset_t set, isSignal;
sigemptyset(&set);
if (sigaddset(&set, SIGUSR1) == -1) { /* ... */ }
while (1) {
if (sigpending(&isSignal) != 0) { /* .. */ }
else if (sigismember(&isSignal, SIGUSR1)) {
break;
}
sendKeepAlive();
sleep(SECONDS);
}
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
似乎 pthread_kill(pth, SIGUSR1); 使程序死亡。请问发送信号的正确方法是什么?我应该改用 pthread_sigmask() 吗?
当 OS 传递信号但进程或线程已阻止它时,信号处于挂起状态。如果您还没有阻止 SIGUSR1,那么它将被传递并且 SIGUSR1 的默认处置是终止该进程。你sigpending在这种情况下什么都不做;它被有效地绕过。首先使用pthread_sigmask或(可选)处理它来阻止 SIGUSR1 。
总之,这是一个可疑的设计。使用阻塞/sigpending 代码,根据设置的 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);
}
Run Code Online (Sandbox Code Playgroud)
选项 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);
}
Run Code Online (Sandbox Code Playgroud)
选项 3 如果可以,请使用其他一些机制。建议。