我刚刚编写了以下例程来处理EINTR错误。 该例程如下所示,
while((s = sem_wait(&w4compl)) == -1)
{
if (errno == EINTR)
{
perror("call interrupted by sig. handler\n");
continue;
}
else
printf("Other Error Generated\n");
}
所以,在这里我看不到打印的“被信号处理程序中断的呼叫\ n”语句。如何测试它以便打印相同(我该如何执行if(errno == EINTR)的部分)。
答案 0 :(得分:1)
安装信号处理程序,并导致传递信号(使用alarm()
,setitimer()
或timer_create()
+ timer_settime()
),以便传递信号将中断sem_wait()
通话。
请考虑以下示例程序:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
static void dummy_handler(int signum)
{
}
static int install_dummy_handler(int signum)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = dummy_handler;
act.sa_flags = 0;
return sigaction(signum, &act, NULL);
}
static const char *errname(const int errnum)
{
switch (errnum) {
case EINTR: return "EINTR";
case EINVAL: return "EINVAL";
default: return "(other)";
}
}
int main(void)
{
sem_t s;
if (install_dummy_handler(SIGALRM) == -1) {
fprintf(stderr, "Cannot install ARLM signal handler: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
sem_init(&s, 0, 0);
alarm(1);
if (sem_wait(&s) == -1) {
const int errnum = errno;
printf("sem_wait() failed with errno == %s (%d; %s).\n",
errname(errnum), errnum, strerror(errnum));
} else
printf("sem_wait() succeeded.\n");
return EXIT_SUCCESS;
}
在main()
中,我们为SIGALRM信号安装了一个信号处理程序。信号处理程序函数是否执行任何操作都没有关系,因为信号的传递会导致“慢速”系统调用返回EINTR错误。 (只要安装该处理程序时未使用SA_RESTART标志 。如果您查看act.sa_mask
中的install_dummy_handler()
,就会发现我们根本没有使用任何标志。在man 2 sigaction
手册页中描述了所有标志和sigaction()
的用法。)
在main()
中,我们首先初始化信号量,然后将警报设置一秒钟。实际的挂钟时间过去后,SIGALRM信号会升高。
请注意,尽管SIGALRM对于该示例和类似目的而言是很好的选择,但您可能想要使用POSIX per-process interval timers。
接下来,我们只需在信号量上调用sem_wait()
,然后检查结果即可。实际上,如果您编译并运行上述 example.c ,例如
gcc -Wall -O2 example.c -lpthread -o example
./example
程序将输出
sem_wait() failed with errno == EINTR (4; Interrupted system call).
一秒钟后。
答案 1 :(得分:0)
如果系统调用被中断,那么在Linux上几乎任何系统调用都可以返回EINTR
。
来自man page(重点是我):
sem_wait()
递减(锁定)sem
指向的信号量。如果 信号量的值大于零,则递减 继续,函数立即返回。如果信号量 当前的值为零,则调用将阻塞直到其中一个 可以执行减量操作(即信号量值 上升到零以上),或信号处理程序中断通话。
要触发这种情况,您应该确保sem_wait
系统调用被阻止(正在等待),然后向该线程发送信号(具有处理程序)。
一些伪代码:
sigint_handler:
return
thread2:
<Your while loop from the question>
main:
signal(SIGINT, sigint_handler) // Setup signal handler
sem_wait(&w4compl)
t2 = start_thread(thread2)
sleep(5) // Hack to make sure thread2 is blocked
pthread_kill(t2, SIGINT)