linux - poll() can't detect event when socket is closed locally? -
i'm working on project port tcp/ip client program onto embedded arm-linux controller board. client program written in epoll(). however, target platform quite old; kernel available 2.4.x, , epoll() not supported. decided rewrite i/o loop in poll().
but when i'm testing code, found poll() not act expected : won't return when tcp/ip client socket closed locally, thread. i've wrote simple codes 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 peer\n"); close(fdlist[0].fd); exit(-1); } if(fdlist[0].revents & pollin) { if( read(fdlist[0].fd, buf, sizeof(buf)) < 0) { printf("closed peer\n"); close(fdlist[0].fd); exit(-1); } } } return 0; }
in code first create tcp client socket, set non-blocking mode, add poll(), , close() socket in thread. , result is: "pollnval" never printed while socket closed.
is expected behavior of poll() ? if choose select() instead of poll() ?
yes, expected behavior. solve using shutdown() on socket instead of close().
see e.g. http://www.faqs.org/faqs/unix-faq/socket/ section 2.6
edit: reason expected poll() , select() reacts events happening on 1 of fd's. close() removes fd, not exist @ anymore, , can't have events associated it.
Comments
Post a Comment