【问题标题】:_GNU_SOURCE macro and epoll_wait behaviour_GNU_SOURCE 宏和 epoll_wait 行为
【发布时间】:2017-05-05 16:09:53
【问题描述】:

我在一个有多个线程的应用程序上工作。其中之一用于 epoll。这个应用程序还捕获SIGINT 信号并执行一些终结。在我设置_GNU_SOURCE 宏之前,一切都很理想。这使得程序卡在了线上:

int n = epoll_wait(epfd, events, N, -1);

因此,设置_GNU_SOURCE 可以防止所有(recv)等待呼叫在SIGINT 上中断。为什么会这样?什么是解决方法?

我特别想使用sched_setaffinity。这需要CPU_SET,它仅适用于_GNU_SOURCE

更新

我如何捕捉SIGINT

static volatile int running = 1;
static void int_handler(int i) {
      running = 0;
}

然后在main:

signal(SIGINT, int_handler);

【问题讨论】:

  • 如何“捕捉到SIGINT 信号”?
  • @KerrekSB ,我已经更新了问题
  • 如果您使用sigactionsa_flags 清零)而不是signal,是否有效?
  • @MarkPlotnick,是的,这有帮助!你能解释一下区别吗?
  • 我会写一个答案。简短版本:_GNU_SOURCE 为您提供许多 BSD 版本,如果您使用 signal,则包括 BSD“安全信号”。 sigaction,OTOH,允许您使用标志指定是否重新启动系统调用。

标签: c pthreads signals posix epoll


【解决方案1】:

在 GNU/Linux 上,/usr/include 中的大多数非内核头文件都由提供 glibc 的相同包提供。当 glibc 提供了一个函数的多个实现时,您可以使用feature_test_macros_GNU_SOURCE 在各种实现中进行选择。

当您定义_GNU_SOURCE 时,它还定义了_BSD_SOURCE,并且在较新版本的glibc 上,_DEFAULT_SOURCE。定义这些宏后,头文件将安排为您提供某些功能的 BSD 版本。 signal 是这些功能之一。

在各种风格的 UNIX 下,signal 做的事情略有不同。您遇到的区别:某些“慢”系统调用在发送信号时被中断时会发生什么。在 V7 和 System III(和 System V)上,处理程序返回后,系统调用将返回 EINTR 错误。在4.2BSD 上,系统调用将重新启动。

如果您使用 POSIX 标准的 sigaction 而不是 signal,则可以通过设置或清除 struct sigactionsa_flags 中的 SA_RESTART 标志来选择系统调用是否可重新启动。

在 glibc 2.19 中,System V 版本的 signal 最终调用带有标志 SA_RESTORER|SA_INTERRUPT|SA_NODEFER|SA_RESETHANDsigaction,而 BSD 版本调用带有标志 SA_RESTORER|SA_RESTARTsigaction

使用sigaction 的另一个原因:正如@KerrekSB 指出的那样,在多线程应用程序中使用signal 具有未指定的行为。

【讨论】:

    猜你喜欢
    • 2011-11-09
    • 2013-08-24
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多