第十五章 创建Callout Library - 处理 UNIX 信号处理错误
处理 UNIX
信号处理错误
在 UNIX
及相关操作系统下运行时,如果进程收到信号,某些系统调用可能会失败,最常见的是打开、读取、写入、关闭、ioctl
和暂停。如果函数使用任何这些系统调用,代码必须能够区分真正的错误、Ctrl-C
和应重新启动的调用。
以下函数允许检查异步事件并在 $ZF
中设置新的警报处理程序。函数声明包含在 iris-cdzf.h
中:
sigrtclr()
int sigrtclr();
— 清除重试标志。应在使用 sigrtchk() 之前调用一次。
dzfalarm()
int dzfalarm();
— 建立新的 `SIGALRM 处理程序。
进入 $ZF
时,会自动保存先前的处理程序。退出时会自动恢复。用户程序不应改变任何其他信号的处理。
sigrtchk()
int sigrtchk();
— 检查异步事件。每当以下系统调用之一失败时就应该调用:open、close、read、write、ioctl、pause
或进程收到信号时失败的任何调用。它返回一个代码,指示用户应采取的操作:
-1
— 不是信号。检查I/O
错误。查看errno
变量的内容。0
— 其他信号。从中断点重新开始操作。1
—SIGINT/SIGTERM
。使用SIGTERM“return 0”
退出 $ZF
。这些信号被适当地捕获。
用于控制某些设备的典型 $ZF
函数将使用类似于以下伪代码的逻辑:
if ((fd = open(DEV_NAME, DEV_MODE)) < 0) {
Set some flags
Call zferror
return 0;
}
如果进程收到信号,open
系统调用可能会失败。通常这种情况不是错误,应该重新启动操作。但是,根据信号,可能会采取其他操作。因此,为了考虑所有可能性,请考虑使用以下代码:
sigrtclr();
while (TRUE) {
if (sigrtchk() == 1) return 1 or 0;
if ((fd = open(DEV_NAME, DEV_MODE)) < 0) {
switch (sigrtchk()) {
case -1:
/* This is probably a real device error */
Set some flags
Call zferror
return 0;
case 0:
/* A innocuous signal was received. Restart. */
continue;
case 1:
/* Someone is trying to terminate the job. */
Do cleanup work
return 1 or 0;
}
}
else break;
}
/*
Code to handle the normal situation:
open() system call succeeded
*/
注意:记住:错误处理代码绝不能改变信号的处理,除非调用 dzfalarm()
来建立新的 SIGALRM
处理程序。