HuangJie HuangJie - 3 months ago 30
C Question

signal handler in child thread

I tried to install SIGINT handler for the child thread in the code below. I expect the child thread to print hello when it receives SIGINT from the parent process. 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;
}

Answer

There are several problems.

1) The signal handler signature is not correct. It should take an int whereas you define it with no parameter. i.e.

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). See signal(7) for details. You can instead use write(2) to print that message:

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. So, signal() may not have been installed yet. So, you need to make sure signal() is installed before pthread_kill() could send SIGINT.


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.

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