在处理 CSAPP 中的作业问题 8.25 时,我参考了其解决方案:https://dreamanddead.github.io/CSAPP-3e-Solutions/。提供的解决方案包括以下 C 代码:
#include <stdio.h>
#include "csapp.h"
sigjmp_buf buf;
void handler(int sig) {
/* jump */
siglongjmp(buf, 1);
}
char* tfgets(char* s, int size, FILE* stream) {
char* result;
if (!sigsetjmp(buf, 1)) {
alarm(5);
if (signal(SIGALRM, handler) == SIG_ERR)
unix_error("set alarm handler error");
return fgets(s, size, stream);
} else {
/* run out of time */
return NULL;
}
}
tfgets
功能是fgets
具有超时功能。然而,使用 siglongjmp 跳出 IO 操作的安全性令人担忧。
使用 siglongjmp 中断 IO 操作并突然退出是否安全?
我在 stackoverflow 上找不到任何文档或相关问题。
不!
从这个处理程序中执行 siglongjmp
是
不安全的。您可以破坏
fgets
正在运行的流的状态。
不要执行
sigsetjmp/siglongjmp
,而是让信号处理程序设置一个全局变量(例如 volatile int alarm_fired;)
。
然后,如果处理程序触发,
fgets
应返回 NULL
并且 errno
应设置为 EINTR
。
您可以(安全地)检查返回值和
errno
值。您还可以检查alarm_fired
。
旁注: 你有竞争条件。
在执行
signal
之后设置信号处理程序(使用 alarm
)。在系统负载较重的情况下,信号可能会在您有机会设置处理程序之前触发。
将
alarm
放在 signal
调用之后。