【问题标题】:Can a system call be programmatically interrupted?可以以编程方式中断系统调用吗?
【发布时间】:2018-11-02 13:47:22
【问题描述】:

我正在尝试为我的 ZeroMQ 应用程序(我通过 cppzmq C++ 层使用)编写一个单元测试。我的问题是,当我尝试关闭上下文时,有时(看似随机)会失败。我不知道为什么,除了错误代码设置为 EINTR,意味着系统调用中断。

要为这种行为编写一个(失败的)单元测试(然后我可以尝试修复),我在想 (see also this PR),如果我能以某种方式欺骗这些被中断的系统调用,那将会很有用。在这个欺骗的系统调用中,我可以先调用常规系统调用,然后在返回之前手动将错误代码设置为 EINTR。例如,我想将recv 替换为:

ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
    ssize_t result = ::recv(sockfd, buf, len, flags);
    errno = EINTR;
    return result;
}

这可能吗?这是明智的(我能预料到问题吗?如果有的话)?还有其他方法可以解决我的单元测试问题吗?

【问题讨论】:

  • 如果你希望你的recv 覆盖总是以-EINTR 失败,根本不要进行实际的系统调用。只需{ errno=EINTR; return -1; }。
  • 这个:: 看起来像 C++。
  • @PSkocik 我应该更清楚地说明我是通过我自己没有编写的库(ZeroMQ)间接调用系统调用。
  • @alk 我只能使用 5 个标签。事实上,如前所述,我通过它的 C++ 接口使用这个库。我在这里使用了 C 标记,因为 POSIX 函数都是 C。
  • 我现在正在研究从一个单独的分叉进程中使用 ptrace,如果这会产生令人满意的解决方案,我会报告。

标签: c unit-testing zeromq system-calls interrupt


【解决方案1】:

只要在阻塞系统调用期间接收到正确配置的中断,就会返回EINTR。

可能最容易引发的信号是SIGALRM,只需调用即可安排:

alarm(1);
recv(...);

一秒后你会收到SIGALRM。

如果您不想等待 1 秒,可以使用 setitimer() 获得亚秒级精度。

【讨论】:

  • 这很有趣!会尝试。不过,我想知道:如何在通过另一个(ZeroMQ)函数间接调用系统调用的自动化测试设置中正确获取此中断的时间?
  • @egpbos:这取决于服务器的类型。您可以尝试设置一个不回复该请求的服务器。由于这是一个测试,您可以在相同的过程中设置服务器。在服务器代码中放置好sleep() 可以解决问题。如果您无法在正确的服务器点插入sleep(),也许您可​​以在另一个线程中运行它并SIGSUSPEND 它...或者您可以模拟协议足以欺骗客户端代码进入您想要的recv() 调用失败...
猜你喜欢
  • 2018-06-11
  • 1970-01-01
  • 2011-02-13
  • 2011-03-19
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多