首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >信号处理程序终止程序

信号处理程序终止程序
EN

Stack Overflow用户
提问于 2019-03-07 00:35:31
回答 1查看 82关注 0票数 0

我尝试使用sigaction安装一个信号处理程序,然后在单个线程上调用它,如下所示:

代码语言:javascript
复制
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,然后整个应用程序终止。在信号处理程序完成后,程序/线程不应该继续吗?

问候

EN

回答 1

Stack Overflow用户

发布于 2019-03-07 18:20:27

主要问题是restore original signal handler执行得太早。

我编写了一个SystemTap脚本来跟踪do_sigactiondo_signal,如下所示:

代码语言:javascript
复制
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());
    }
}

结果是

代码语言:javascript
复制
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

原因:

  • STEP1:在主线程中将信号处理程序设置为my_signal_handler
  • STEP2:在主线程中还原原始信号处理程序
  • STEP3:当子线程从内核模式返回到用户模式时执行do_signal。

显然,这里存在并发问题。可以在执行do_signal之前恢复信号处理程序。在恢复信号处理程序之前需要进行并发控制,或者将恢复处理程序移动到my_signal_handler函数,如:

代码语言:javascript
复制
#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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55027995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档