C 如何编写测试用例来验证linux中sem_wait函数返回的EINTR

C 如何编写测试用例来验证linux中sem_wait函数返回的EINTR,c,linux,semaphore,C,Linux,Semaphore,我刚刚编写了下面的例程来处理EINTR错误。 程序如下所示: while((s = sem_wait(&w4compl)) == -1) { if (errno == EINTR) { perror("call interrupted by sig. handler\n"); continue; } else printf("Ot

我刚刚编写了下面的例程来处理EINTR错误。 程序如下所示:

while((s = sem_wait(&w4compl)) == -1)
{
        if (errno == EINTR)
        {
                perror("call interrupted by sig. handler\n");
                continue;
        }
        else
                printf("Other Error Generated\n");
}

因此,在这里我无法看到print“callinterrupted by sig.handler\n”语句。如何测试它以使其打印相同的内容(如何执行if(errno==EINTR)部分)。

如果系统调用被中断,Linux上几乎任何系统调用都可以返回
EINTR

从(我的)重点:

sem\u wait()
减少(锁定)由
sem
指向的信号量。如果 信号量的值大于零,则减量 继续,函数立即返回。如果信号量 当前值为零,则调用阻塞,直到 可以执行减量(即信号量值 高于零),或信号处理程序中断调用

要触发这种情况,您应该确保
sem_wait
系统调用被阻止(等待),然后向线程发送信号(具有处理程序)

一些psuedo代码:

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)
sigint\u处理程序:
返回
线程2:
主要内容:
信号(SIGINT,SIGINT\u处理程序)//设置信号处理程序
sem_wait(&w4compl)
t2=起始螺纹(螺纹2)
sleep(5)//进行黑客攻击以确保thread2被阻止
pthread_kill(t2,SIGINT)

安装一个信号处理程序,并发送一个信号(使用
报警()
设置定时器()
,或
定时器创建()
+
定时器设置时间()
),这样信号的发送将中断
sem\u等待()
调用


考虑以下示例程序:

#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;
}
程序将输出


一秒钟后。

嗨,p.p.如果这个问题已经回答了,你能给我链接吗?它在你的问题中是链接的。@p.p.如果你仔细看,那实际上不是一个好的副本。当然,标题很好,也很一般,但最重要的答案都是“不要重新调用
fclose()
”,这在这里并没有真正的帮助。同意乔纳森的观点。这对我帮助不大。@JonathonReinhart链接的问题是针对单元测试EINTR的,OP在这里也问了这个问题。这里有不错的答案。当然,fclose就是一个例子(这里是sem_的帖子)。我不确定每个可能返回EINTR的系统调用都需要一个不同的问题,以及如何对其进行单元测试。谢谢@Jonathan Reinhart。这里的例程调用了一个线程。那个么我怎样才能给线程一个SIGINT信号呢?用来给线程发送一个信号。为了理解,OP应该在这里阻止哪个系统调用?为什么是SIGINT?@Jonathan我将在现有代码中尝试伪代码并检查。1。使用
信号
不是一个好主意(最好使用sigaction)。2.除了作为同步机制的
sleep
是一个糟糕的选择之外,
sleep
本身也可能会被信号中断(我仍然不明白
sleep
在main中是如何确保它在线程中被阻塞的)。@NiravPatel:请注意,如果有多个线程,信号必须指向执行
sem\u wait()的线程
调用,并且导致阻塞调用中断的是向用户空间处理函数传递信号,而不是信号本身。在某些情况下,您可能需要一个信号对,主信号在除一个线程外的所有线程中都被阻塞,以便其信号处理程序可以将信号(使用未阻塞的辅助信号)“转发”到每个现有的其他线程,以中断多个线程。如果您需要更多详细信息或示例,请告诉我。
gcc -Wall -O2 example.c -lpthread -o example
./example
sem_wait() failed with errno == EINTR (4; Interrupted system call).