简体   繁体   English

子线程中的信号处理程序

[英]signal handler in child thread

I tried to install SIGINT handler for the child thread in the code below. 我尝试在下面的代码中为子线程安装SIGINT处理程序。 I expect the child thread to print hello when it receives SIGINT from the parent process. 我希望子线程在从父进程接收SIGINT时打印hello。 However, nothing comes out and the program exits immediately. 然而,没有任何结果,程序立即退出。

#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;
}

There are several problems. 有几个问题。

1) The signal handler signature is not correct. 1)信号处理程序签名不正确。 It should take an int whereas you define it with no parameter. 它应该采用int而你没有参数定义它。 ie

static void proxy_singnal_handler(){

should be 应该

static void proxy_singnal_handler(int sig){

2) You can't call functions that are not async-signal-safe from a signal handler ( printf() in your case). 2)您不能从信号处理程序(在您的情况下为printf()中调用非异步信号安全的函数。 See signal(7) for details. 有关详细信息,请参阅信号(7) You can instead use write(2) to print that message: 您可以改为使用write(2)来打印该消息:

printf("Hello\n");

can be: 可:

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

3) When main thread sends SIGINT , the t_consensus thread might not have even started. 3)当线程发送SIGINTt_consensus线程可能甚至没有启动。 So, signal() may not have been installed yet. 因此, signal()可能尚未安装。 So, you need to make sure signal() is installed before pthread_kill() could send SIGINT . 因此,您需要确保 pthread_kill()发送SIGINT 之前安装了signal()


Just to demonstrate it, I have added some sleep calls (see comments in the code). 为了演示它,我添加了一些睡眠调用(请参阅代码中的注释)。 But please note that sleep() is not a good way to synchronization and if you intend to adapt this example then you should use a conditional variable instead. 但请注意,sleep() 不是一种很好的同步方法,如果你打算改编这个例子,那么你应该使用条件变量。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.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(int sig){
    write(1, "Hello\n", 6);
    return;
}

static void* t_consensus(void *arg){
    signal(SIGINT,proxy_singnal_handler);
    while(1); /* infinite loop */
    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);
    sleep(2); /* delay to ensure signal handler is installed */
    pthread_kill(proxy->sub_thread,SIGINT);
    sleep(2); /* delay to ensure signal gets executed before the process exits */
    return 0;
}

Since @Maxim Egorushkin wanted to see a solution that exits gracefully and uses semaphores: 因为@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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM