需要知道如何中断所有pthreads

时间:2015-05-05 21:13:10

标签: multithreading pthreads signals

在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()的调用,但只有一个线程在堆栈跟踪中有处理程序。可以这样做吗?

2 个答案:

答案 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()中的信号并不是必需的:信号掩码是每个线程,并且正在执行信号处理程序的线程不会再次发出信号。

可能问题在于如何安装信号处理程序或设置线程信号掩码。