poll() 无限期等待,尽管指定了超时
poll() waits indefinitely although timeout is specified
我正在编写一个 C 客户端-服务器程序,其中客户端必须从服务器接收大量数据。因为我希望我的客户端在服务器出现问题时不要无限期地等待 recv()
(例如,发送数据时它停止了),所以我选择使用 poll()
中指定的函数linux man page.
我的代码如下所示:
while (...)
{
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
retry:
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1 && errno == EINTR)
goto retry;
else if (r == -1)
err_sys("poll() failed");
else if (r == 0)
err_sys("timeout expired");
recv(...)
}
其中 sock
是与套接字关联的文件描述符,TIMEOUT
设置为 5 秒,我指定 POLLIN
作为事件,因为我对读取数据感兴趣。
问题
根据男人的说法:
The timeout argument specifies the number of milliseconds that poll()
should block waiting for a file descriptor to become ready. The call
will block until either:
(1) a file descriptor becomes ready;
(2) the call is interrupted by a signal handler; or
(3) the timeout expires.
但是,程序会无限期地阻塞在 poll()
函数上,即使在我停止服务器后超时已过期(我使用了 valgrind)。我还尝试将事件设置为 POLLIN | POLLPRI
(为了捕捉一些异常情况),但它没有用。我多次阅读文档,但我无法弄清楚是什么导致了这个问题。
其他信息
我正在使用 Xubuntu 18.04,gcc 版本 7.4.0,目标 x86_64
即使没有数据可读,您的代码也会无条件调用 recv()
。事实上,如果 poll()
不是 return 和 error/timeout.
,那么您完全忽略了 fds.revents
字段
您的循环应该更像这样:
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
do {
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1) {
if (errno == EINTR) continue;
perror("poll() failed");
break;
}
else if (r == 0) {
printf("timeout expired");
break;
}
else if (fds.revents & POLLIN) {
r = recv(...);
if (r < 0) {
perror("recv() failed");
break;
}
else if (r == 0) {
printf("socket disconnected\n");
break;
}
else {
// process data as needed...
}
}
else if (fds.revents & (POLLERR | POLLNVAL)) {
printf("socket error\n");
break;
}
}
while (1);
close(sock);
我正在编写一个 C 客户端-服务器程序,其中客户端必须从服务器接收大量数据。因为我希望我的客户端在服务器出现问题时不要无限期地等待 recv()
(例如,发送数据时它停止了),所以我选择使用 poll()
中指定的函数linux man page.
我的代码如下所示:
while (...)
{
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
retry:
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1 && errno == EINTR)
goto retry;
else if (r == -1)
err_sys("poll() failed");
else if (r == 0)
err_sys("timeout expired");
recv(...)
}
其中 sock
是与套接字关联的文件描述符,TIMEOUT
设置为 5 秒,我指定 POLLIN
作为事件,因为我对读取数据感兴趣。
问题
根据男人的说法:
The timeout argument specifies the number of milliseconds that poll() should block waiting for a file descriptor to become ready. The call will block until either:
(1) a file descriptor becomes ready; (2) the call is interrupted by a signal handler; or (3) the timeout expires.
但是,程序会无限期地阻塞在 poll()
函数上,即使在我停止服务器后超时已过期(我使用了 valgrind)。我还尝试将事件设置为 POLLIN | POLLPRI
(为了捕捉一些异常情况),但它没有用。我多次阅读文档,但我无法弄清楚是什么导致了这个问题。
其他信息
我正在使用 Xubuntu 18.04,gcc 版本 7.4.0,目标 x86_64
即使没有数据可读,您的代码也会无条件调用 recv()
。事实上,如果 poll()
不是 return 和 error/timeout.
fds.revents
字段
您的循环应该更像这样:
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
do {
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1) {
if (errno == EINTR) continue;
perror("poll() failed");
break;
}
else if (r == 0) {
printf("timeout expired");
break;
}
else if (fds.revents & POLLIN) {
r = recv(...);
if (r < 0) {
perror("recv() failed");
break;
}
else if (r == 0) {
printf("socket disconnected\n");
break;
}
else {
// process data as needed...
}
}
else if (fds.revents & (POLLERR | POLLNVAL)) {
printf("socket error\n");
break;
}
}
while (1);
close(sock);