poll() returns macOS 上超过 256 个描述符的 EINVAL
poll() returns EINVAL for more than 256 descriptors on macOS
这是崩溃的示例代码:
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <limits.h>
#define POLL_SIZE 1024
int main(int argc, const char * argv[]) {
printf("%d\n", OPEN_MAX);
struct pollfd *poll_ = calloc(POLL_SIZE, sizeof(struct pollfd));
if (poll(poll_, POLL_SIZE, -1) < 0)
if (errno == EINVAL)
perror("poll error");
return 0;
}
如果您将 POLL_SIZE
设置为 256 或更少,代码就可以正常工作。有趣的是,如果你 运行 Xcode 中的这段代码,它会正常执行,但如果你 运行 自己的二进制文件,你就会崩溃。
输出是这样的:
10240
poll error: Invalid argument
根据poll(2)
:
[EINVAL] The nfds argument is greater than OPEN_MAX or the
timeout argument is less than -1.
如你所见,POLL_SIZE
比限制小了很多,超时正好是-1,却崩溃了。
我手动构建的clang版本:
Configured with: prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.41)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
在 Unix 系统上,processes have limits on resources. See e.g. getrlimit. You might change them (using setrlimit
) and your sysadmin can also change them (e.g. configure these limits at startup or login time). There is a limit RLIMIT_NOFILE
related to file descriptors. Read also about the ulimit
bash builtin. See also sysconf 和 _SC_OPEN_MAX
。
里面的poll system call is given a not-too-big array, and it is bad taste (possible, but inefficient) to repeat some file descriptor。所以在实践中,你经常会使用它和一个很小的数组,提到 different (但有效)文件描述符。 poll
的第二个参数是有用条目的数量(实际上,都是不同的),而不是分配的数组大小。
您可能会处理许多文件描述符。了解 C10K problem.
顺便说一句,您的代码没有崩溃。 poll
如记录的那样失败(但没有崩溃)。
您应该阅读一些 POSIX 编程书籍。 Advanced Linux Programming 是免费提供的,其中大部分是关于 POSIX(不是 Linux 特定)的东西。
这是崩溃的示例代码:
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <limits.h>
#define POLL_SIZE 1024
int main(int argc, const char * argv[]) {
printf("%d\n", OPEN_MAX);
struct pollfd *poll_ = calloc(POLL_SIZE, sizeof(struct pollfd));
if (poll(poll_, POLL_SIZE, -1) < 0)
if (errno == EINVAL)
perror("poll error");
return 0;
}
如果您将 POLL_SIZE
设置为 256 或更少,代码就可以正常工作。有趣的是,如果你 运行 Xcode 中的这段代码,它会正常执行,但如果你 运行 自己的二进制文件,你就会崩溃。
输出是这样的:
10240
poll error: Invalid argument
根据poll(2)
:
[EINVAL] The nfds argument is greater than OPEN_MAX or the
timeout argument is less than -1.
如你所见,POLL_SIZE
比限制小了很多,超时正好是-1,却崩溃了。
我手动构建的clang版本:
Configured with: prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.41)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
在 Unix 系统上,processes have limits on resources. See e.g. getrlimit. You might change them (using setrlimit
) and your sysadmin can also change them (e.g. configure these limits at startup or login time). There is a limit RLIMIT_NOFILE
related to file descriptors. Read also about the ulimit
bash builtin. See also sysconf 和 _SC_OPEN_MAX
。
里面的poll system call is given a not-too-big array, and it is bad taste (possible, but inefficient) to repeat some file descriptor。所以在实践中,你经常会使用它和一个很小的数组,提到 different (但有效)文件描述符。 poll
的第二个参数是有用条目的数量(实际上,都是不同的),而不是分配的数组大小。
您可能会处理许多文件描述符。了解 C10K problem.
顺便说一句,您的代码没有崩溃。 poll
如记录的那样失败(但没有崩溃)。
您应该阅读一些 POSIX 编程书籍。 Advanced Linux Programming 是免费提供的,其中大部分是关于 POSIX(不是 Linux 特定)的东西。