_GNU_SOURCE 宏和 epoll_wait 行为

_GNU_SOURCE macro and epoll_wait behaviour

我在开发一个有多个线程的应用程序。其中之一用于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);

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

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

在各种风格的 UNIX 下,signal 做的事情略有不同。您遇到的不同之处:某些 "slow" 系统调用在发送信号时被中断时会发生什么。在 V7 和 System III (and System V), an EINTR error would be returned from the system call after the handler returns. On 4.2BSD 上,系统调用将重新启动。

如果您使用 POSIX-standard sigaction 而不是 signal,您可以通过设置或清除 SA_RESTART 标志来选择系统调用是否可重启struct sigactionsa_flags.

在 glibc 2.19 中,signal 的 System V 版本最终调用带有标志 SA_RESTORER|SA_INTERRUPT|SA_NODEFER|SA_RESETHANDsigaction,而 BSD 版本调用带有标志 [=25] 的 sigaction =].

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