在Linux中,我正在模拟一个嵌入式系统,该系统有一个线程可以将消息传递到外部世界。如果某个线程检测到一个难以克服的问题,我的目标是停止其轨道中的所有其他线程(留下有用的堆栈跟踪)并仅允许消息传递线程继续。所以在我的仿真环境中,我想“pthread_kill(tid,SIGnal)”每个“tid”。 (我有一个列表。我正在使用SIGTSTP。)不幸的是,只有一个线程正在获取信号。 “sigprocmask()”无法取消屏蔽信号。这是我当前的(非工作)处理程序:
void
wait_until_death(int sig)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, sig);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
for (;;)
pause();
}
我得到验证所有pthread_kill()的调用,但只有一个线程在堆栈跟踪中有处理程序。可以这样做吗?
答案 0 :(得分:2)
这是不可能的。问题是您停止的某些线程可能会保留您要继续运行的线程所需的锁,以便继续前进。完全放弃这个想法。相信我,这只会给你带来极大的痛苦。
如果你真的必须这样做,让所有其他线程在已知的安全位置调用一个条件生成点,在这些位置它们没有锁定,可以防止任何其他线程到达下一个条件生成点。但是非常很难做到并且非常容易出现死锁,我强烈建议不要尝试它。
答案 1 :(得分:1)
这个最小的例子似乎以你想要的方式运行 - 除主线程之外的所有线程最终都在wait_until_death()
中等待:
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#define NTHREADS 10
pthread_barrier_t barrier;
void
wait_until_death(int sig)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, sig);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
for (;;)
pause();
}
void *thread_func(void *arg)
{
pthread_barrier_wait(&barrier);
for (;;)
pause();
}
int main(int argc, char *argv[])
{
const int thread_signal = SIGTSTP;
const struct sigaction sa = { .sa_handler = wait_until_death };
int i;
pthread_t thread[NTHREADS];
pthread_barrier_init(&barrier, NULL, NTHREADS + 1);
sigaction(thread_signal, &sa, NULL);
for (i = 0; i < NTHREADS; i++)
pthread_create(&thread[i], NULL, thread_func, NULL);
pthread_barrier_wait(&barrier);
for (i = 0; i < NTHREADS; i++)
pthread_kill(thread[i], thread_signal);
fprintf(stderr, "All threads signalled.\n");
for (;;)
pause();
return 0;
}
请注意,取消阻塞wait_until_death()
中的信号并不是必需的:信号掩码是每个线程,并且正在执行信号处理程序的线程不会再次发出信号。
可能问题在于如何安装信号处理程序或设置线程信号掩码。