我尝试使用sigaction安装一个信号处理程序,然后在单个线程上调用它,如下所示:
void
my_signal_handler ( int signo, siginfo_t *info, void *extra )
{
printf("my signal handler\n" );
}
int threadsupervisor() {
<...>
struct sigaction action;
struct sigaction oldHandler;
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = my_signal_handler;
sigaction(SIGRTMIN + 3, &action, &oldHandler );
// send signal to affected thread
pthread_kill( threadId, SIGRTMIN + 3 );
// restore original signal handler
sigaction( SIGRTMIN + 3, &oldHandler, NULL );
}线程确实接收到SIG37,然后整个应用程序终止。在信号处理程序完成后,程序/线程不应该继续吗?
问候
发布于 2019-03-07 18:20:27
主要问题是restore original signal handler执行得太早。
我编写了一个SystemTap脚本来跟踪do_sigaction和do_signal,如下所示:
probe begin {
printf("start.\n");
}
probe kernel.function("do_signal") {
if ("test_sigaction" == execname()) {
printf("do_signal pid=%d\n", pid());
}
}
probe kernel.function("handle_signal") {
if ("test_sigaction" == execname()) {
printf("handle_signal pid=%d\n", pid());
}
}
probe kernel.function("do_sigaction").return {
if ("test_sigaction" == execname()) {
printf("do_sigaction: ret=%d sig=%d act=%p oact=%p pid=%d\n",
$return, @entry($sig), @entry($act),
@entry($oact), pid());
}
}结果是
do_sigaction: ret=0 sig=37 act=0xffffc90006ccbec8 oact=0xffffc90006ccbee8 pid=45920 //STEP1
do_sigaction: ret=0 sig=37 act=0xffffc90006ccbec8 oact=0x0 pid=45920 //STEP2
do_signal pid=45920 //STEP3
do_signal pid=45920原因:
显然,这里存在并发问题。可以在执行do_signal之前恢复信号处理程序。在恢复信号处理程序之前需要进行并发控制,或者将恢复处理程序移动到my_signal_handler函数,如:
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
struct sigaction oldHandler;
void my_signal_handler(int signo, siginfo_t *info, void *extra)
{
printf("my signal handler\n" );
// restore original signal handler
sigaction( SIGRTMIN + 3, &oldHandler, NULL );
}
int threadsupervisor(pthread_t thread_id)
{
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = my_signal_handler;
sigaction(SIGRTMIN + 3, &action, &oldHandler );
// send signal to affected thread
pthread_kill(thread_id, SIGRTMIN + 3 );
return 0;
}
void *test_thread(void *args)
{
long loop = 0;
while(1) {
printf("sleep %ld\n", ++loop);
sleep(1);
}
return (void *)NULL;
}
int main()
{
pthread_t thread_id;
pthread_create(&thread_id, NULL, test_thread, NULL);
threadsupervisor(thread_id);
pthread_join(thread_id, NULL);
return 0;
}https://stackoverflow.com/questions/55027995
复制相似问题