zoukankan      html  css  js  c++  java
  • poll() can't detect event when socket is closed locally?

    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
    ");
        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
    ");
                exit(-1);
            }
            if(fdList[0].revents & POLLOUT) {
                printf("connected
    ");
                fdList[0].events = POLLIN;
            }
            if(fdList[0].revents & POLLHUP ) {
                printf("closed by peer
    ");
                close(fdList[0].fd);
                exit(-1);
            }
            if(fdList[0].revents & POLLIN) {
                if( read(fdList[0].fd, buf, sizeof(buf)) < 0) {
                    printf("closed by peer
    ");
                    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

     

  • 相关阅读:
    MYSQL实战-------丁奇(极客时间)学习笔记
    java并发编程实践——王宝令(极客时间)学习笔记
    分布式锁-----秒杀系统
    MYSQL IN 出现的慢查询问题
    携程2018年年度技术合集
    MySQL分库分表
    Mysql 千万级别数据数据查询
    视频协议融合平台人脸识别/车牌识别平台EasyCVR内调用接口二次开发疑难解答
    国标GB28181/Ehone协议视频人脸识别/车牌识别平台EasyCVR新版本支持大华SDK接入开发记录
    国标GB28181协议接入视频智能分析平台EasyCVR的设备用ws_flv为什么会有无法播放的情况?
  • 原文地址:https://www.cnblogs.com/kex1n/p/7375572.html
Copyright © 2011-2022 走看看