多线程环境中的信号处理程序行为

时间:2020-03-24 09:10:18

标签: c linux multithreading pthreads signals

我有以下程序,其中只有一个线程安装信号处理程序。但是,当我通过向每个线程发送信号来测试代码时,所有线程都会执行信号处理程序。 是否所有线程共享相同的信号处理程序。我以为只有在产生这些线程的主进程安装了信号处理程序时,它才会发生(线程共享信号处理程序)。

还有一个问题是关于信号处理程序执行的上下文。是否可以确保发送到特定线程的信号将在给定场景下在相同的线程上下文中执行?

void handler(int signo, siginfo_t *info, void *extra)
{
        printf("handler id %d and thread id %d\n",syscall( SYS_gettid ),pthread_self());
}
void signalHandler()
{
   struct sigaction sa;
   sa.sa_flags = SA_SIGINFO;
   sa.sa_sigaction = handler;
   sigaction(SIGSEGV, &sa, NULL);
   //sigaction(SIGINT, &sa, NULL);
}
void *threadfn0(void *p)
{
        signalHandler();
        printf("thread0\n");
        while ( 1 )
        {
                pause();
        }
}
void *threadfn1(void *p)
{
        while(1){
                printf("thread1\n");
                sleep(15);
        }
        return 0;
}
void *threadfn2(void *p)
{
        while(1){
                printf("thread2\n");
                sleep(15);
        }
        return 0;
}
int main()
{
        pthread_t t0,t1,t2;
        pthread_create(&t0,NULL,threadfn0,NULL);
        printf("T0 is %d\n",t0);
        pthread_create(&t1,NULL,threadfn1,NULL);
        printf("T1 is %d\n",t1);
        pthread_create(&t2,NULL,threadfn2,NULL);
        printf("T2 is %d\n",t2);
        sleep(10);
        pthread_kill(t2,SIGSEGV);
        sleep(10);
        pthread_kill(t1,SIGSEGV);
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        pthread_join(t0,NULL);
        return 0;
}

输出:

T0 is 1110239552
T1 is 1088309568
T2 is 1120729408
thread0
thread1
thread2
handler id 18878 and thread id 1120729408
thread2
thread1
handler id 18877 and thread id 1088309568
thread1

2 个答案:

答案 0 :(得分:2)

来自manpage for signal(7)

信号处理是每个进程的属性:在多线程应用程序中,所有线程的特定信号处理都是相同的。

因此,所有线程共享相同的处理程序,是的。如果您使用modelBuilder .Entity<QRLink>() .Property(p => p.Code) .HasColumnAnnotation(@"Index", new IndexAnnotation(new IndexAttribute(@"IX_Code") { IsUnique = true })); modelBuilder .Entity<QRLink>() .Property(p => p.Code) .HasColumnAnnotation(@"CustomIndex", new CustomIndexAnnotation(new CustomIndexAttribute(@"IX_Code") { IsUnique = true, Where = @"Code IS NOT NULL" })); 将信号发送到特定线程,则该线程应执行处理程序(当然,取决于使用pthread_sigmask()设置的线程的信号掩码)。

还请注意,您不能在信号处理程序中安全地使用pthread_kill()或其他stdio函数。请参见signal-safety(7)中的允许功能列表。

答案 1 :(得分:0)

所有线程共享信号处理程序。您可以使用pthread_sigmask()来选择哪些线程具有哪些信号被阻塞或解除阻塞,因此可以执行该处理程序。如果多个线程具有相同的信号不受阻塞,则它们中的任何一个都可以执行处理程序。

因此,清理并修复的示例如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/syscall.h>

static void handler (int signo, siginfo_t *info, void *extra)
{
    printf ("SIGNAL %u, handler id %lu and thread id %lu\n", signo, syscall (SYS_gettid), pthread_self ());
}

static void signalHandler (void)
{
   struct sigaction sa;
   sa.sa_flags = SA_SIGINFO;
   sa.sa_sigaction = handler;
   sigaction (SIGSEGV, &sa, NULL);
}

static void *threadfn0 (void *p)
{
    signalHandler ();

    sigset_t set;
    sigfillset (&set);
    pthread_sigmask (SIG_UNBLOCK, &set, NULL);

    printf ("thread0\n");
    while (1) {
        pause ();
    }
}

static void *threadfn1 (void *p)
{
    while (1) {
        printf ("thread1\n");
        sleep (15);
    }
    return 0;
}

static void *threadfn2 (void *p)
{
    while (1) {
        printf ("thread2\n");
        sleep (15);
    }
    return 0;
}

int main (int argc, char *argv[])
{
    pthread_t t0, t1, t2;

    // By default, block all signals in all threads and
    // unblock them only in one thread after signal handler
    // is set up, to avoid race conditions
    sigset_t set;
    sigfillset (&set);
    pthread_sigmask (SIG_BLOCK, &set, NULL);

    pthread_create (&t0, NULL, threadfn0, NULL);
    printf ("T0 is %lu\n", t0);
    pthread_create (&t1, NULL, threadfn1, NULL);
    printf ("T1 is %lu\n", t1);
    pthread_create (&t2, NULL, threadfn2, NULL);
    printf ("T2 is %lu\n", t2);

    pthread_kill (t2, SIGSEGV);
    pthread_kill (t1, SIGSEGV);
    pthread_kill (t0, SIGSEGV);

    pthread_join (t2, NULL);
    pthread_join (t1, NULL);
    pthread_join (t0, NULL);

    return 0;
}
相关问题