我尝试在下面的代码中为子线程安装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;
}
答案 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;
}