C和pthread_join停止程序中的信号接收器线程

时间:2016-11-05 00:55:17

标签: c multithreading

我正在尝试构建一个具有2/3线程的基本程序。主线程,信号器线程和接收器线程。我试图让它成为主线程启动信号器和接收器线程。然后,信号器线程应该向接收器线程发送10个SIGUSR1信号并增加全局计数器。接收器线程应该接收10个信号,同时为接收到的每个信号增加自己的计数器。

我遇到的麻烦是最后将线程连接在一起,特别是加入接收器线程。如果我尝试将它们连接在一起,大多数时候程序会停止,我认为因为接收器线程还没有完成它的工作(也许它已经错过了信号?)所以它永远不会完成。我想也许就是这种情况,所以我在信号器线程中引入了一个等待命令来减慢速度,但这并没有改变任何东西。

如果我注释掉pthread_join(接收器,NULL),程序就会运行,但它只会在大多数情况下捕获一个信号。我认为这是因为接收器线程没有太多时间运行。 (虽然有时它会捕获各种数量,具体取决于它何时被抢占?)

在程序中保留pthread_join(接收器,NULL)使其停止19/20次,但是1/20时间程序返回10个发送的信号和10个接收的信号。这让我相信它与先发制人有关,但我不明白为什么它会在第一时间停滞不前。

现在我只是让接收器线程接收线程,而接收的计数器是< 10.理想情况下,我只想在(1)循环中保留它,但是我再也不知道如何将其加入主线程而不冻结所有内容。

如果有人能帮我弄清楚为什么错过信号/为什么程序会冻结我会非常感激。我怀疑我没有为接收器正确设置信号掩码,但我不知道我应该怎么做。这是代码:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>

void *receivetest(void *args);
void *signaltest(void *args);


int received = 0;
int sent = 0;
pthread_t signaler;
pthread_t receiver;
sigset_t mask;

int main(){

    //setting up the signal mask
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);

    //creation of both threads
    pthread_create(&receiver, NULL, receivetest, NULL);
    pthread_create(&signaler, NULL, signaltest, NULL);


    pthread_join(signaler, NULL);
    pthread_join(receiver, NULL);

    //printing results after joining them back
    printf("I'm the main function\n");
    printf("Receieved: %d, sent: %d\n", received, sent);


}

void *signaltest(void *args){
    int i = 0;
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread
        pthread_kill(receiver, SIGUSR1);
        sent++;
    }
}

void *receivetest(void *args){
    int c; //sigwait needs int 
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread
    while(received < 10){ //waits for 10 signals and increments receieved
        sigwait(&mask, &c);
        received++;
    }
}

2 个答案:

答案 0 :(得分:1)

信号就是这样不起作用。如果线程在相同信号已经挂起时收到信号,则不会发生任何事情。请使用适当的线程间通信方法,而不是信号。

答案 1 :(得分:0)

你几乎做对了。建议阻止来自主线程的信号,以保护所有新线程不会错误处理信号。

pthread_sigmask()之后创建的任何线程都继承了sigmask。第一个参数告诉pthread_sigmask()如何处理第二个参数中列出的信号。

这一行pthread_sigmask(SIG_BLOCK, &mask, NULL)应该放在主线程中,而不是放在信号处理程序上。您的原始代码也会起作用,但如果信号发送到错误的线程,则会终止整个过程。

此外,发送方发送信号的速度比接收方可以处理的速度快。通过在每次迭代之间休眠1秒钟,接收器将能够赶上。

我冒昧地修改了你的代码。我在发送者和接收者中添加了一些打印件,这样你就会知道它在做什么。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void receivetest(void); //function does not return anything
void signaltest(void); // does not accept parameter either.


int received = 0;
int sent = 0;
pthread_t signaler;
pthread_t receiver;
sigset_t mask;

int main(){

    //setting up the signal mask
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread

    //creation of both threads
    pthread_create(&receiver, NULL, (void *)receivetest, NULL);
    pthread_create(&signaler, NULL, (void *)signaltest, NULL);


    pthread_join(signaler, NULL);
    pthread_join(receiver, NULL);

    //printing results after joining them back
    printf("I'm the main function\n");
    printf("Receieved: %d, sent: %d\n", received, sent);
    return 0;

}

void signaltest(void){
    int i = 0;
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread
        printf("Sending signal\n");
        pthread_kill(receiver, SIGUSR1);
        sleep(1); // Don't send signals too fast
        sent++;
    }
}

void receivetest(void){
    int c; //sigwait needs int 
    while(received < 10){ //waits for 10 signals and increments receieved
        sigwait(&mask, &c);
        printf("Signal received\n");
        received++;
    }
}

输出:

Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
I'm the main function
Receieved: 10, sent: 10
相关问题