如何使函数异步信号安全?

时间:2013-06-06 16:29:07

标签: c++ c linux asynchronous signals

我有以下sigaction处理函数

void signal_term_handler(int sig)
{
    printf("EXIT :TERM signal Received!\n");
    int rc = flock(pid_file, LOCK_UN | LOCK_NB);
    if(rc) {
        char *piderr = "PID file unlock failed!";
        fprintf(stderr, "%s\n", piderr);
        printf(piderr);
    }
    abort();
}

有人告诉我,flockprintf不是异步信号安全的。我在list中找不到flock的备用异步信号安全功能。

并根据以上链接:

  

当信号中断不安全功能和信号捕获时   函数调用不安全的函数,行为未定义

有没有办法让flock异步信号安全?或者,当我收到flock信号时,是否有其他解决方案来执行TERM

3 个答案:

答案 0 :(得分:4)

您可以使用fcntl()替代flock()。

答案 1 :(得分:4)

flock()通常是异步信号安全的,因为它是一个系统调用。它的语义使得以不同方式实现它变得困难。它不在POSIX的异步信号安全函数列表中,因为它根本不在POSIX中。

您可能不需要显式解锁,因为当引用打开的文件描述的所有文件描述符都关闭时会自动释放flock()锁。

printf()fprintf()来电应替换为适当的write()来电。 stdio函数不在异步信号安全函数列表中,并且通常强烈异步信号不安全。

最好将abort()调用替换为将信号设置为默认操作并将其重新发送为self;这样,shell知道您的程序因信号而退出,并且可以在适当的时候中止命令序列。

答案 2 :(得分:0)

您可以在信号处理程序中使用exit()而不是abort(),然后使用atexit()将不安全的函数放入退出处理程序。

更新:通常,您不应在信号处理程序中放置任何可能阻塞的系统调用。避免这种情况的一种方法是在信号处理程序中设置一个标志,然后在主循环的上下文中执行所需的功能。

volatile int shutdown = 0;

void signal_term_handler(int sig)
{
    shutdown = 1;
}

void cleanup() {
    printf("EXIT :TERM signal Received!\n");
    int rc = flock(pid_file, LOCK_UN | LOCK_NB);
    if(rc) {
        char *piderr = "PID file unlock failed!";
        fprintf(stderr, "%s\n", piderr);
        printf(piderr);
    }
}

void *workerFunction(void *arg) {
    while (!shutdown) {
       ... do stuff ...
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    //...
    pthread_create(...,workerFunction,...);
    pthread_join(...);
    cleanup();
    return 0;
}