I'm wondering what should be done when poll set these bits? Close socket, ignore it or what?
我想知道在轮询设置这些位时应该怎么做?关闭套接字,忽略它或什么?
4 个解决方案
#1
11
A POLLHUP
means the socket is no longer connected. In TCP, this means FIN has been received and sent.
POLLHUP表示套接字不再连接。在TCP中,这意味着FIN已被接收和发送。
A POLLERR
means the socket got an asynchronous error. In TCP, this typically means a RST has been received or sent. If the file descriptor is not a socket, POLLERR
might mean the device does not support polling.
POLLERR表示套接字出现异步错误。在TCP中,这通常意味着已经接收或发送了RST。如果文件描述符不是套接字,则POLLERR可能意味着设备不支持轮询。
For both of the conditions above, the socket file descriptor is still open, and has not yet been closed (but shutdown()
may have already been called). A close()
on the file descriptor will release resources that are still being reserved on behalf of the socket. In theory, it should be possible to reuse the socket immediately (e.g., with another connect()
call).
对于上述两个条件,套接字文件描述符仍处于打开状态,尚未关闭(但可能已经调用了shutdown())。文件描述符上的close()将释放仍代表套接字保留的资源。理论上,应该可以立即重用套接字(例如,使用另一个connect()调用)。
A POLLNVAL
means the socket file descriptor is not open. It would be an error to close()
it.
POLLNVAL表示套接字文件描述符未打开。关闭()它会是一个错误。
#2
8
It depend on the exact error nature. Use getsockopt() to see the problem:
它取决于确切的错误性质。使用getsockopt()来查看问题:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Values: http://www.xinotes.net/notes/note/1793/
值:http://www.xinotes.net/notes/note/1793/
The easiest way is to assume that the socket is no longer usable in any case and close it.
最简单的方法是假设套接字在任何情况下都不再可用并关闭它。
#3
2
POLLNVAL
means that the file descriptor value is invalid. It usually indicates an error in your program, but you can rely on poll
returning POLLNVAL
if you've closed a file descriptor and you haven't opened any file since then that might have reused the descriptor.
POLLNVAL表示文件描述符值无效。它通常表示程序中存在错误,但是如果您关闭了文件描述符并且之前没有打开任何可能重用了描述符的文件,则可以依赖轮询返回POLLNVAL。
POLLERR
is similar to error events from select
. It indicates that a read
or write
call would return an error condition (e.g. I/O error). This does not include out-of-band data which select
signals via its errorfds
mask but poll
signals via POLLPRI
.
POLLERR类似于select的错误事件。它表示读或写调用将返回错误条件(例如I / O错误)。这不包括通过其errorfds掩码选择信号但通过POLLPRI轮询信号的带外数据。
POLLHUP
basically means that what's at the other end of the connection has closed its end of the connection. POSIX describes it as
POLLHUP基本上意味着连接另一端的内容已关闭其连接的结束。 POSIX将其描述为
The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.
设备已断开连接。此活动和POLLOUT是互斥的;如果发生挂断,则流永远不可写。
This is clear enough for a terminal: the terminal has gone away (same event that generates a SIGHUP: the modem session has been terminated, the terminal emulator window has been closed, etc.). POLLHUP
is never sent for a regular file. For pipes and sockets, it depends on the operating system. Linux sets POLLHUP
when the program on the writing end of a pipe closes the pipe, and sets POLLIN|POLLHUP
when the other end of a socket closed the socket, but POLLIN
only for a socket shutdown. Recent *BSD set POLLIN|POLLUP
when the writing end of a pipe closes the pipe, and the behavior for sockets is more variable.
这对于终端来说已经足够清楚了:终端已经消失(产生SIGHUP的同一事件:调制解调器会话已经终止,终端仿真器窗口已经关闭等)。永远不会发送POLLHUP作为常规文件。对于管道和插座,它取决于操作系统。当管道写入端的程序关闭管道时Linux设置POLLHUP,当套接字的另一端关闭套接字时设置POLLIN | POLLHUP,但POLLIN仅用于套接字关闭。最近的* BSD在管道的写入端关闭管道时设置POLLIN | POLLUP,并且套接字的行为更加可变。
#4
0
Minimal FIFO example
最小FIFO示例
Once you understand when those conditions happen, it should be easy to know what to do with them.
一旦了解了这些情况何时发生,就应该很容易知道如何处理它们。
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
Compile with:
编译:
gcc -o poll.out -std=c99 poll.c
Usage:
用法:
sudo mknod -m 666 poll0.tmp p
./poll.out
On another shell:
在另一个shell上:
printf a >poll0.tmp
POLLHUP
POLLHUP
If you don't modify the source: ./poll.out
outputs:
如果您不修改源:./ poll.out输出:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
So:
所以:
-
POLLIN
happens when input becomes available - POLLIN在输入可用时发生
-
POLLHUP
happens when the file is closed by theprintf
- 当printf关闭文件时发生POLLHUP
-
close(pfd.fd);
andpfd.fd *= -1;
clean things up, and we stop receivingPOLLHUP
- 关闭(pfd.fd);和pfd.fd * = -1;清理东西,我们停止接收POLLHUP
-
poll
hangs forever - 民意调查永远挂起
This is the normal operation.
这是正常的操作。
You could now repoen the FIFO to wait for the next open
, or exit the loop if you are done.
您现在可以重新启动FIFO以等待下一次打开,或者如果完成则退出循环。
POLLNAL
POLLNAL
If you comment out pfd.fd *= -1;
: ./poll.out
prints:
如果你注释掉pfd.fd * = -1 ;: ./poll.out打印:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
and loops forever.
并永远循环。
So:
所以:
-
POLLIN
andPOLLHUP
andclose
happened as before - POLLIN和POLLHUP和关闭发生在以前
- since we didn't set
pfd.fd
to a negative number,poll
keeps trying to use thefd
that we closed - 因为我们没有将pfd.fd设置为负数,所以poll继续尝试使用我们关闭的fd
- this keeps returning
POLLNVAL
forever - 这让POLLNVAL永远回归
So we see that this shouldn't have happened, and indicates a bug in your code.
所以我们发现这不应该发生,并且表明代码中存在错误。
POLLERR
POLLERR
I don't know how to generate a POLLERR
with FIFOs. Let me know if there is way. But it should be possible with file_operations
of a device driver.
我不知道如何使用FIFO生成POLLERR。如果有办法让我知道。但是应该可以使用设备驱动程序的file_operations。
Tested in Ubuntu 14.04.
在Ubuntu 14.04中测试过。
#1
11
A POLLHUP
means the socket is no longer connected. In TCP, this means FIN has been received and sent.
POLLHUP表示套接字不再连接。在TCP中,这意味着FIN已被接收和发送。
A POLLERR
means the socket got an asynchronous error. In TCP, this typically means a RST has been received or sent. If the file descriptor is not a socket, POLLERR
might mean the device does not support polling.
POLLERR表示套接字出现异步错误。在TCP中,这通常意味着已经接收或发送了RST。如果文件描述符不是套接字,则POLLERR可能意味着设备不支持轮询。
For both of the conditions above, the socket file descriptor is still open, and has not yet been closed (but shutdown()
may have already been called). A close()
on the file descriptor will release resources that are still being reserved on behalf of the socket. In theory, it should be possible to reuse the socket immediately (e.g., with another connect()
call).
对于上述两个条件,套接字文件描述符仍处于打开状态,尚未关闭(但可能已经调用了shutdown())。文件描述符上的close()将释放仍代表套接字保留的资源。理论上,应该可以立即重用套接字(例如,使用另一个connect()调用)。
A POLLNVAL
means the socket file descriptor is not open. It would be an error to close()
it.
POLLNVAL表示套接字文件描述符未打开。关闭()它会是一个错误。
#2
8
It depend on the exact error nature. Use getsockopt() to see the problem:
它取决于确切的错误性质。使用getsockopt()来查看问题:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Values: http://www.xinotes.net/notes/note/1793/
值:http://www.xinotes.net/notes/note/1793/
The easiest way is to assume that the socket is no longer usable in any case and close it.
最简单的方法是假设套接字在任何情况下都不再可用并关闭它。
#3
2
POLLNVAL
means that the file descriptor value is invalid. It usually indicates an error in your program, but you can rely on poll
returning POLLNVAL
if you've closed a file descriptor and you haven't opened any file since then that might have reused the descriptor.
POLLNVAL表示文件描述符值无效。它通常表示程序中存在错误,但是如果您关闭了文件描述符并且之前没有打开任何可能重用了描述符的文件,则可以依赖轮询返回POLLNVAL。
POLLERR
is similar to error events from select
. It indicates that a read
or write
call would return an error condition (e.g. I/O error). This does not include out-of-band data which select
signals via its errorfds
mask but poll
signals via POLLPRI
.
POLLERR类似于select的错误事件。它表示读或写调用将返回错误条件(例如I / O错误)。这不包括通过其errorfds掩码选择信号但通过POLLPRI轮询信号的带外数据。
POLLHUP
basically means that what's at the other end of the connection has closed its end of the connection. POSIX describes it as
POLLHUP基本上意味着连接另一端的内容已关闭其连接的结束。 POSIX将其描述为
The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.
设备已断开连接。此活动和POLLOUT是互斥的;如果发生挂断,则流永远不可写。
This is clear enough for a terminal: the terminal has gone away (same event that generates a SIGHUP: the modem session has been terminated, the terminal emulator window has been closed, etc.). POLLHUP
is never sent for a regular file. For pipes and sockets, it depends on the operating system. Linux sets POLLHUP
when the program on the writing end of a pipe closes the pipe, and sets POLLIN|POLLHUP
when the other end of a socket closed the socket, but POLLIN
only for a socket shutdown. Recent *BSD set POLLIN|POLLUP
when the writing end of a pipe closes the pipe, and the behavior for sockets is more variable.
这对于终端来说已经足够清楚了:终端已经消失(产生SIGHUP的同一事件:调制解调器会话已经终止,终端仿真器窗口已经关闭等)。永远不会发送POLLHUP作为常规文件。对于管道和插座,它取决于操作系统。当管道写入端的程序关闭管道时Linux设置POLLHUP,当套接字的另一端关闭套接字时设置POLLIN | POLLHUP,但POLLIN仅用于套接字关闭。最近的* BSD在管道的写入端关闭管道时设置POLLIN | POLLUP,并且套接字的行为更加可变。
#4
0
Minimal FIFO example
最小FIFO示例
Once you understand when those conditions happen, it should be easy to know what to do with them.
一旦了解了这些情况何时发生,就应该很容易知道如何处理它们。
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
Compile with:
编译:
gcc -o poll.out -std=c99 poll.c
Usage:
用法:
sudo mknod -m 666 poll0.tmp p
./poll.out
On another shell:
在另一个shell上:
printf a >poll0.tmp
POLLHUP
POLLHUP
If you don't modify the source: ./poll.out
outputs:
如果您不修改源:./ poll.out输出:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
So:
所以:
-
POLLIN
happens when input becomes available - POLLIN在输入可用时发生
-
POLLHUP
happens when the file is closed by theprintf
- 当printf关闭文件时发生POLLHUP
-
close(pfd.fd);
andpfd.fd *= -1;
clean things up, and we stop receivingPOLLHUP
- 关闭(pfd.fd);和pfd.fd * = -1;清理东西,我们停止接收POLLHUP
-
poll
hangs forever - 民意调查永远挂起
This is the normal operation.
这是正常的操作。
You could now repoen the FIFO to wait for the next open
, or exit the loop if you are done.
您现在可以重新启动FIFO以等待下一次打开,或者如果完成则退出循环。
POLLNAL
POLLNAL
If you comment out pfd.fd *= -1;
: ./poll.out
prints:
如果你注释掉pfd.fd * = -1 ;: ./poll.out打印:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
and loops forever.
并永远循环。
So:
所以:
-
POLLIN
andPOLLHUP
andclose
happened as before - POLLIN和POLLHUP和关闭发生在以前
- since we didn't set
pfd.fd
to a negative number,poll
keeps trying to use thefd
that we closed - 因为我们没有将pfd.fd设置为负数,所以poll继续尝试使用我们关闭的fd
- this keeps returning
POLLNVAL
forever - 这让POLLNVAL永远回归
So we see that this shouldn't have happened, and indicates a bug in your code.
所以我们发现这不应该发生,并且表明代码中存在错误。
POLLERR
POLLERR
I don't know how to generate a POLLERR
with FIFOs. Let me know if there is way. But it should be possible with file_operations
of a device driver.
我不知道如何使用FIFO生成POLLERR。如果有办法让我知道。但是应该可以使用设备驱动程序的file_operations。
Tested in Ubuntu 14.04.
在Ubuntu 14.04中测试过。