Linux 脚本和程序对SIGINT的处理方案,脚本通过kill给程序传递信号

性能测试中,Tester程序由start.sh脚本来启动。现在的需求是:用户按下ctrl-c,程序能graceful退出,从而不用重启板子。问题 是:ctrl-c产生信号SIGINT,但是这个信号是传递给脚本进程的,不是传递给Tester进程的。所以这里就存在一个信号传递的问题。解决办法如 下:

1. 在脚本中加入代码:

Code: Select all
forward_sigint()
{
    # check out the tester's pid
    testerpid=$(cat /tmp/tester.pid)
    kill -2 $testerpid

    # call analyser and quit
    echo "Calling analyser..."
    ./Analyser/analyser

    echo "Test finished. Thanks."
    rm -f /tmp/tester.pid

    exit 0
}
   
......

# trap control-c signal and forwards it to tester
trap forward_sigint SIGINT


这 样ctrl-c按下后,函数forward_sigint得到执行。然后这个函数取出tester程序的pid,利用kill命令发送SIGINT信号给 tester,从而使tester程序graceful退出。注意,这里的kill命令是shell自带的一个命令,不是/bin/kill程序。也可以 使用/bin/kill程序来发送信号,效果一样的。

2. 在Tester程序中添加代码:

首先在main函数中添加:

Code: Select all
// catch SIGINT interrupt
signal(SIGINT, stop_playing);

// write pid into /tmp/tester to make test script knows our pid
write_pid_to_temp_file();

然后是这两个函数的实现:

/*
* Write our pid to file /tmp/tester.pid
* This makes start script knows our pid and send SIGINT to us
* when the user pressed ctrl-c
*/
void write_pid_to_temp_file()
{
    FILE *pidfile = fopen("/tmp/tester.pid", "wb");
    char content[10];
    sprintf(content, "%d", getpid());
    fputs(content, pidfile);
    fclose(pidfile);
}


/*
* Stop playing and quit
*/
void stop_playing(int sig)
{
    DEBUG_OUTPUT("Ctrl-C caught, stop playing and quit...");
    // restore the SIGINT handler
    signal(SIGINT, SIG_DFL);

    // make sure the glib mainloop is running
    while (!g_main_loop_is_running(loop))
        wait_seconds(1);

    g_main_loop_quit(loop);
}


OK,就是这样了。关键点就是当程序通过脚本启动时,信号是传递给脚本进程的,不是传递给正在执行的程序进程的。所以信号需要传递一下方可。
posted @ 2011-03-26 10:15  super119  阅读(1011)  评论(0编辑  收藏  举报