子线程中的信号处理程序

时间:2016-08-09 16:18:26

标签: c multithreading pthreads signals

我尝试在下面的代码中为子线程安装SIGINT处理程序。我希望子线程在从父进程接收SIGINT时打印hello。然而,没有任何结果,程序立即退出。

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

typedef struct proxy_node_t{
    pthread_t sub_thread;
    pthread_t p_self;
}proxy_node;

proxy_node* proxy;

static void proxy_singnal_handler(){
    printf("Hello\n");
    return;
}

static void* t_consensus(void *arg){
    signal(SIGINT,proxy_singnal_handler);
    sleep(1);
    return NULL;
}

int main(int argc, char **argv)
{
    proxy = (proxy_node*)malloc(sizeof(proxy_node));
    proxy->p_self = pthread_self();
    pthread_create(&proxy->sub_thread,NULL,t_consensus,NULL);
    pthread_kill(proxy->sub_thread,SIGINT);
    sleep(1);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

有几个问题。

1)信号处理程序签名不正确。它应该采用int而您没有参数定义它。 即

static void proxy_singnal_handler(){

应该是

static void proxy_singnal_handler(int sig){

2)您无法从信号处理程序(在您的情况下为printf())中调用非 async-signal-safe 的函数。有关详细信息,请参阅signal(7)。您可以使用write(2)打印该消息:

printf("Hello\n");

可以是:

write(1, "Hello\n", 6);

3)当 main 线程发送SIGINT时,t_consensus线程可能甚至没有启动。因此,signal()可能尚未安装。因此,您需要确保在 signal()发送pthread_kill()之前已安装

为了证明这一点,我添加了一些睡眠调用(请参阅代码中的注释)。但是请注意,sleep()不是是一种很好的同步方法,如果你打算改编这个例子,那么你应该使用条件变量。

SIGINT

答案 1 :(得分:0)

由于@Maxim Egorushkin希望看到一个优雅退出并使用信号量的解决方案:

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

typedef struct proxy_node_t{
    pthread_t sub_thread;
    pthread_t p_self;
}proxy_node;

proxy_node* proxy;

static void proxy_singnal_handler(int sig)
{
    write(1, "Hello\n", 6);
    return;
}

sem_t sema1;
sem_t sema2;

static void* t_consensus(void *arg)
{
  signal(SIGINT,proxy_singnal_handler);
  sem_post(&sema1);   /*notify main thread that signal-handler is installed*/
  sem_wait(&sema2);   /*ensure thread exists to be pthread_kill'ed, could use sigsuspend instead*/
  return NULL;
}
 int main(int argc, char **argv)
{
  sem_init(&sema1, 0, 0);
  sem_init(&sema2, 0, 0);
  proxy = (proxy_node*)malloc(sizeof(proxy_node));
  proxy->p_self = pthread_self();
  pthread_create(&proxy->sub_thread,NULL,t_consensus,NULL);
  sem_wait(&sema1);    /*wait until the thread has installed the signal handler*/
  pthread_kill(proxy->sub_thread,SIGINT);
  sem_post(&sema2);    /*not strictly necessary if the thread uses sigsuspend*/
  pthread_join(proxy->sub_thread, NULL);
  free(proxy);         /*not strictly necessary before exiting*/
  sem_destroy(&sema1);
  sem_destroy(&sema2);
  return 0;
}