在信号处理程序中仍应避免使用全局变量但退出的函数?

时间:2012-09-10 19:06:25

标签: c signals signal-handling reentrancy

当我研究一些关于使用C的unix编程的东西时,我已经知道在信号处理程序中应避免使用不可重入的函数,但如果我有类似的东西:

int main(int argc, char** argv){
     ...
    fileFd=open(...) 
    signal(SIGUSR1, signalHandler)
    ...
}


void signalHandler(int signo){
    switch(signo){

    case SIGUSR1:
        myExit(EXIT_FAILURE);   
        break;

    default: 
        break;

    }
}

myExit在哪里

void myExit(int ret){

    ...DO STUFF...
    close(fileFd);
    exit(ret);

}

和fileFd是一个全局变量,如果我没记错的话,myExit的内容是不可重入的......但是在信号处理程序中使用它仍然是一个问题,即使它会导致程序的退出? 谢谢,如果这是一个愚蠢的问题,任何帮助都表示赞赏和抱歉。

3 个答案:

答案 0 :(得分:3)

您可以在信号处理程序中安全地执行的唯一操作是设置volatile sig_atomic_t变量。请通过检查已接收到信号(在信号处理程序之外),在程序的主循环中执行所有处理。如果你必须开始做非便携式的东西,那么至少考虑使用_Exit()或_exit()。某些C库将保证某些功能是信号安全的,但不能保证在不同的系统上工作。

答案 1 :(得分:0)

取决于“...... DO STUFF ......”可能会出现问题。如果在那里完成的东西可能没有完成两次(比如释放相同的指针),它可能会崩溃。

在您的特定情况下,如果close(fileFD)是影响全局状态的唯一事物,并且您的文件访问API允许双重关闭文件,则这可能不会成为问题。

答案 2 :(得分:0)

如果您使用任何异步不安全的功能,仍然不安全。像USR1这样的异步信号可能出现在程序中的任何两条指令之间,包括在某些库代码的关键部分(锁定部分)的中间。

因此,例如,如果中断发生在malloc的中间,则在信号处理程序中调用free(例如清理)将会死锁。