【问题标题】:Signal handling among pthreadspthread 之间的信号处理
【发布时间】:2014-11-29 15:53:46
【问题描述】:

我正在尝试学习进程和线程之间的信号处理。几个问题的答案将帮助我更好地理解它。

我知道一个进程可以向进程组发送信号并允许多个进程接收相同的信号,但我不确定线程​​。

  • 发送到所有 pthread 的信号是否可以同时由多个 pthread 处理?

我设置我的程序使用pthread_sigmask() 阻止所有信号,我有两个线程使用sigwait(SIGUSR1) 等待信号,并且我让主线程发送 SIGUSR1 信号。当只有一个线程处理信号时,似乎一切正常(我在另一个线程中注释掉了代码),但是当两个线程都运行sigwait() 代码时,它挂起或终止太快。

代码贴在下面。

sig_atomic_t signals = 0;
sig_atomic_t sigusr1_signals = 0;
sig_atomic_t sigusr2_signals = 0;
sig_atomic_t count = 0;
sig_atomic_t totalcount = 0;

sigset_t globalset;

int WAIT = 1;           /* false = 0, true = 1 */

static int SIGNALS_SENT = 0;
static int SIGNALS_RECEIVED = 0;

void *sig1handler1(void *argv);

void *reporterhandler(void *argv);

int random_number(int min, int max);

int main(void) {

    pthread_t threads[2];   /* create an array to store a number of threads */

    //int *p_status = &status;
    sigfillset(&globalset);
    pthread_sigmask(SIG_BLOCK, &globalset, NULL);

    /* Generate signal handling threads */
    if (pthread_create(&threads[0], NULL, &sig1handler1, NULL) > 0)
    {
        printf("Thread creation failure!\n");
        return -1;
    }


    /* create reporting thread */
    if (pthread_create(&threads[1], NULL, &reporterhandler, NULL) > 0)
    {
        printf("Thread creation failure!\n");
        return -1;
    }

    /* Signal all threads to begin work concurrently */
    WAIT = 0;

    int c = 0;
    while(c < 100)
    {
        int value = random_number(1, 2);
        if (value == 1)
            kill(0, SIGUSR1);
        else
            kill(0, SIGUSR2);

        SIGNALS_SENT++;
        c++;
        usleep(10000);
    }

    kill(0, SIGINT);


    /* Wait for each thread to finish and join */
    int i = 0;
    for(i = 0; i < 2; i++)
    {
        if (pthread_join(threads[i], NULL) > 0)
        {
            printf("Thread [%u] join failure!\n", (unsigned int)threads[i]);
            return -1;
        }

        printf("THREAD [%u] returned.\n", (unsigned int)threads[i]);
    }

    printf("Parent Process [%d] exiting successfully.\n", getpid());
    return EXIT_SUCCESS;
}


void *sig1handler1(void *argv)
{
    pthread_t tid = pthread_self();
    printf("THREAD[%u] sig1handler1: waiting for signal to do some work...\n", (unsigned int)tid);

//  sigset_t myset;
//  sigfillset(&myset);
//  sigdelset(&myset, SIGINT);
//  sigdelset(&myset, SIGUSR1);
//  pthread_sigmask(SIG_SETMASK, &myset, NULL);

    /* Wait for a signal to start work */
    while (WAIT);

    int sig;
    int count = 0;

    while(1)
    {
        sigwait(&globalset, &sig);
        if (sig == SIGUSR1)
        {
            sigusr1_signals++;
            signals++;
            count++;
            //printf("thread1: caught SIGUSR1 signal!\n");
        }
        else if (sig == SIGINT)
        {
            printf("thread1: caught SIGINT signal, detected SIGUSR1 %d times, and terminating!\n", count);          pthread_exit(NULL);
        }
    }

    //printf("THREAD[%u] sig1handler1: doing some work!\n", (unsigned int)tid);
    //return (void *)EXIT_SUCCESS;
    //return (void *)NULL;
    pthread_exit(NULL);
}

void *reporterhandler(void *argv)
{
    pthread_t tid = pthread_self();
    printf("THREAD[%u] reporter: waiting for signal to do some work...\n", (unsigned int)tid);

    int sig;
    int count = 0;

//  sigset_t myset;
//  sigfillset(&myset);
//  sigdelset(&myset, SIGINT);
//  sigdelset(&myset, SIGUSR1);
//  sigdelset(&myset, SIGUSR2);
//  pthread_sigmask(SIG_SETMASK, &myset, NULL);

    /* Wait for a signal to start work */
    while (WAIT);

    while(1)
    {
        sigwait(&globalset, &sig);
        if (sig == SIGUSR1)
        {
            sigusr1_signals++;
            signals++;
            count++;
            totalcount++;
            SIGNALS_RECEIVED++;
        }
        else if (sig == SIGUSR2)
        {
            sigusr2_signals++;
            signals++;
            count++;
            totalcount++;
            SIGNALS_RECEIVED++;
        }
        else if (sig == SIGINT)
        {
            printf("Reporter: SIGUSR1 detected %d times\n", sigusr1_signals);
            printf("Reporter: SIGUSR2 detected %d times\n", sigusr2_signals);
            printf("Reporter: detected %d signals\n", totalcount);
            printf("Reporter: SIGNALS_SENT %d \n", SIGNALS_SENT);
            printf("Reporter: SIGNALS_REC %d \n", SIGNALS_RECEIVED);
            pthread_exit(NULL);
        }

        /* Display Report after detecting 10 signals */
        if (count == 10)
                    sigusr1_signals, sigusr2_signals);

            count = 0;
        }
    }

    //printf("THREAD[%u] reporter: doing some work!\n", (unsigned int)tid);
    pthread_exit(NULL);
}

int random_number(int min, int max)
{
    if (min < max)
    {
        max = max + 1;      /* include the max value */
        return (rand() % (max - min)) + min;
    }

    return -1;
}   

【问题讨论】:

  • 我相信口头禅是“信号被发送到进程”,并且将被传递一次到不忽略信号的线程。
  • 我比较确定信号可以发送到特定线程或所有线程。不知道是不是只有一个人可以处理,但我想他们都可以接收到信号。
  • @0d0a 信号处理程序在您阻止信号然后轮询它们时不相关。
  • 您好 o11c,感谢您提供的信息。我知道您使用其中一种。我的代码使用名称 sighandler 来表示函数,但它们实际上是由线程完成的工作,它坐在那里等待信号。

标签: c multithreading pthreads signals signal-handling


【解决方案1】:
  • 信号是否可以 [be] 发送到所有 pthread [并] 由多个 pthread 同时处理?

不是同时。这些是可能性:

  1. 向进程发送信号 (kill()):在这种情况下,任何侦听信号的线程都可以接收它,但只有一个线程会这样做。
  2. 向进程组发送信号:信号将被传递到组中的所有进程。
  3. 向特定线程 (pthread_kill()) 发送信号:现在您将其发送到特定线程 ID。

原型:

int pthread_kill(pthread_t thread, int sig);

在您的情况下,我认为将信号传递给所有线程的唯一方法是遍历所有线程 ID 以使用 pthread_kill() 发送信号。

【讨论】:

  • 这是我需要找出的。谢谢!我进行了一些实验并发现了同样的事情,但我不确定,因为我不确定我的代码。这解释了它。
猜你喜欢
  • 2011-07-14
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
相关资源
最近更新 更多