_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 sigaction
的 sa_flags
.
在 glibc 2.19 中,signal
的 System V 版本最终调用带有标志 SA_RESTORER|SA_INTERRUPT|SA_NODEFER|SA_RESETHAND
的 sigaction
,而 BSD 版本调用带有标志 [=25] 的 sigaction
=].
使用 sigaction
的另一个原因:正如@KerrekSB 指出的那样,在多线程应用程序中使用 signal
具有未指定的行为。
我在开发一个有多个线程的应用程序。其中之一用于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 sigaction
的 sa_flags
.
在 glibc 2.19 中,signal
的 System V 版本最终调用带有标志 SA_RESTORER|SA_INTERRUPT|SA_NODEFER|SA_RESETHAND
的 sigaction
,而 BSD 版本调用带有标志 [=25] 的 sigaction
=].
使用 sigaction
的另一个原因:正如@KerrekSB 指出的那样,在多线程应用程序中使用 signal
具有未指定的行为。