如何使一个函数异步信号安全

How to make a function async-signal-safe?

本文关键字:信号 安全 异步 函数 何使一      更新时间:2023-10-16

我有以下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, "%sn", piderr);
        printf(piderr);
    }
    abort();
}

有人告诉我,flockprintf不是异步信号安全的。在此列表中,我无法找到flock的替代异步信号安全函数。

,根据上面的链接:

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

是否有办法使flock异步信号安全?或者当我收到TERM信号时,是否有另一种解决方案来执行flock ?

可以使用fcntl()作为flock()的替代方法。

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

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

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

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

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

update:一般来说,你不应该在你的信号处理程序中放置任何可能阻塞的系统调用。避免这种情况的一种方法是在信号处理程序中设置一个标志,然后在主循环的上下文中执行所需的函数。

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, "%sn", 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;
}