[英]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)当主线程发送
SIGINT
, t_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.