8

我有以下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();
}

有人告诉我这不是异步信号安全的flock。而且我在此列表printf中找不到替代的异步信号安全功能 。flock

并根据上面的链接:

当一个信号中断了一个不安全的函数并且信号捕获函数调用了一个不安全的函数时,行为是未定义的

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

4

3 回答 3

4

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

于 2013-06-06T17:12:02.683 回答
4

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

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

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

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

于 2013-06-06T21:21:36.273 回答
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;
}
于 2013-06-06T17:06:15.327 回答