from https://stackoverflow.com/questions/5039608/poll-cant-detect-event-when-socket-is-closed-locally

I'm working on a project that will port a TCP/IP client program onto an embedded ARM-Linux controller board. The client program was originally written in epoll(). However, the target platform is quite old; the only kernel available is 2.4.x, and epoll() is not supported. So I decided to rewrite the I/O loop in poll().

But when I'm testing code, I found that poll() does not act as I expected : it won't return when a TCP/IP client socket is closed locally, by another thread. I've wrote a very simple codes to do some test:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>
#include <poll.h> struct pollfd fdList[1]; void *thread_runner(void *arg)
{
sleep(10);
close(fdList[0].fd);
printf("socket closed\n");
pthread_exit(NULL);
} int main(void)
{
struct sockaddr_in hostAddr;
int sockFD;
char buf[32];
pthread_t handle; sockFD = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sockFD,F_SETFL,O_NONBLOCK|fcntl(sockFD,F_GETFL,0)); inet_aton("127.0.0.1",&(hostAddr.sin_addr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_port = htons(12345);
connect(sockFD,(struct sockaddr *)&hostAddr,sizeof(struct sockaddr)); fdList[0].fd = sockFD;
fdList[0].events = POLLOUT; pthread_create(&handle,NULL,thread_runner,NULL); while(1) {
if(poll(fdList,1,-1) < 1) {
continue;
}
if(fdList[0].revents & POLLNVAL ) {
printf("POLLNVAL\n");
exit(-1);
}
if(fdList[0].revents & POLLOUT) {
printf("connected\n");
fdList[0].events = POLLIN;
}
if(fdList[0].revents & POLLHUP ) {
printf("closed by peer\n");
close(fdList[0].fd);
exit(-1);
}
if(fdList[0].revents & POLLIN) {
if( read(fdList[0].fd, buf, sizeof(buf)) < 0) {
printf("closed by peer\n");
close(fdList[0].fd);
exit(-1);
}
}
}
return 0;
}

 

In this code I first create a TCP client socket, set to non-blocking mode, add to poll(), and close() the socket in another thread. And the result is: "POLLNVAL" is never printed while the socket is closed.

Is that an expected behavior of poll() ? Will it help if I choose select() instead of poll() ?

Answer:

Yes, this is expected behavior. You solve this by using shutdown() on the socket instead of close().

See e.g. http://www.faqs.org/faqs/unix-faq/socket/ section 2.6

EDIT: The reason this is expected is that poll() and select() reacts to events happening on one of their fd's. close() removes the fd, it does not exist at all anymore, and thus it can't have any events associated with it.

It worked. poll() will return with POLLHUP event

 

poll() can't detect event when socket is closed locally?的更多相关文章

  1. java的Socket通信例子及关于java.net.SocketException: Socket is closed错误

    今天写socket数据相互通信的时候,碰到一个及其蛋疼的错误.单向传输数据的时候server与client是没有问题的,但是两个都有输入输出操作的时候就出现了这个问题 java.net.SocketE ...

  2. java.io.IOException: read failed, socket might closed or timeout, read ret: -1

    近期项目中连接蓝牙之后接收蓝牙设备发出的指令功能,在连接设备之后,创建RfcommSocket连接时候报java.io.IOException: read failed, socket might c ...

  3. paramiko 遭遇socket.error: Socket is closed 错误的解决办法

    似乎是connection自己断了解决的办法是在创建conn的时候添加下面这句 conn.keep_this = conn_session 完整代码 def create_a_conn(ip_addr ...

  4. vue app混合开发蓝牙串口连接(报错java.io.IOException: read failed, socket might closed or timeout, read ret: -1;at android.bluetooth.BluetoothSocket.connect at js/BluetoothTool.js:329)

    我使用的uni-app <template> <view class="bluetooth"> <!-- 发送数据 --> <view c ...

  5. The socket is closed!

    关闭mongodb    /usr/local/app/mongidb//bin/mongod   --shutdown  --dbpath /usr/local/data/mongo/data/ 然 ...

  6. 转:sock_ev——linux平台socket事件框架(event loop) .

    上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理:我们再封装一层EventLoop. /************************************ ...

  7. Linux内核3.11的socket busy poll机制避免睡眠切换

    Linux的网络协议栈很独立,上下通过两个接口分别和用户态以及设备相连.也能够看作是北向和南向接口...北向通过socket接口,南向通过qdisc接口(你能够觉得是上层的netdev queue,对 ...

  8. Asynchronous socket communication

    来源:http://www.codeproject.com/Articles/1608/Asynchronous-socket-communication 本地下载 Download source f ...

  9. #include <sys/epoll.h> epoll - I/O event notification facility 服务器端 epoll(7) - Linux manual page http://www.man7.org/linux/man-pages/man7/epoll.7.html

    epoll使用详解(精髓) - Boblim - 博客园 https://www.cnblogs.com/fnlingnzb-learner/p/5835573.html epoll使用详解(精髓) ...

随机推荐

  1. 云计算--hbase shell

    具体的 HBase Shell 命令如下表 1.1-1 所示: 下面我们将以“一个学生成绩表”的例子来详细介绍常用的 HBase 命令及其使用方法. 这里 grad 对于表来说是一个列,course ...

  2. LOJ 2249: 洛谷 P2305: 「NOI2014」购票

    题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...

  3. mongo批量操作存在更新否则插入

    def save_data(ok_ps): ns = [] for ok in ok_ps: ok['last_use_time'] = 0 ok['protocol'] = 0 # 协议类型 0:h ...

  4. H2内嵌数据库使用步骤

    1.找到h2数据库的jar包 D:\repositories\com\h2database\h2\1.4.187\h2-1.4.187.jar 2.双击jar包,配置连接信息 Driver Class ...

  5. springcloud使用Zuul构建微服务网关入门

    为什么要使用微服务网关 不同的微服务一般会经过不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求. 如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会多次请求不同的微 ...

  6. java Foreach与迭代器

    foreach语法主要用于数组,但是它也可以用于Collection对象,下面是一个示例 package object; //: holding/ForEachCollections.java // ...

  7. 如何安装pycharm

    Ubuntu系统安装PyCharm教程(详细图文) 参考(http://jingyan.baidu.com/article/60ccbceb4e3b0e64cab19733.html)  

  8. awk 调用 shell 命令,并传递参数

    from:awk 调用 shell 命令的两种方法:system 与 print shell 向awk传递命令,这样使用即可: awk -v  ...  但反过来呢?awk调用外部命令,同时也传参呢? ...

  9. 【BZOJ】3456: 城市规划(多项式求ln)

    题解 在我写过分治NTT,多项式求逆之后 我又一次写了多项式求ln 我们定义一个数列的指数型生成函数为 \(\sum_{i = 0}^{n} \frac{A_{i}}{i!} x^{i}\) 然后这个 ...

  10. Codeforces 772C 构造 数学 + dp + exgcd

    首先我们能注意到两个数x, y (0 < x , y < m) 乘以倍数互相可达当且仅当gcd(x, m) == gcd(y, m) 然后我们可以发现我们让gcd(x, m)从1开始出发走 ...