Thread: Failed to get POLLHUP event

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    2

    Failed to get POLLHUP event

    According to poll() man, when the server closes socket, this client will receive POLLHUP event if poll() is used. However my program doesn't get it. When I close the socket from server side, the client receives POLLIN instead of POLLHUP. What's wrong with me? The client and server program both run on the same machine, and someone said POLLHUP doesn't work for local network, is that true? How can client know server close a socket? Here is my code. Please give me some suggestions. Thanks. By the way, my system is CentOS 4.4.

    Client program:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <pthread.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <poll.h>
    
    #define MAX_BUFFER	128
    #define DAYTIME_SERVER_PORT	2213
    
    void *secondThread(void *arg)
    {
    	int in, index = 0, limit = MAX_BUFFER, nread;
    	char timebuffer[MAX_BUFFER];
    	int sd = *((int*) arg);
    	printf("sd = %d\n", sd);
    	int count;
    	
    	struct pollfd fds[100];
    	fds[0].fd = sd;
    	fds[0].events = POLLIN | POLLHUP;
    	 
    	while (1) {
    		if ((count = poll(fds, 1, -1)) > 0) {
    			if (fds[0].revents & POLLHUP ) {
    				printf("peer closed. \n");
    				pthread_exit(NULL);
    			} 
    			
    			if (fds[0].revents & POLLERR ) {
    				printf("peer ERR. \n");
    				pthread_exit(NULL);
    			} 
    			if (fds[0].revents & POLLNVAL ) {
    				printf("peer closed. \n");
    				pthread_exit(NULL);
    			} 
    
    			if (fds[0].revents & POLLIN) {
    				printf("Get a event %d\n", count);
    				ioctl(sd, FIONREAD, &nread);
    				if (0 == nread) {
    					printf("nothing to read.\n");
    					pthread_exit(NULL);
    				} else {
    					if (nread > 3) {
    						nread = 3;
    					}
    				while ((in = read(sd, timebuffer+index, nread)) > 0) {
    					index += in;
    					limit -= in;
    				}
    				timebuffer[index] = 0;
    				printf("Read %s from sd (%d). \n", timebuffer, sd);
    				}
    			} 
    		}
    	}
    }
    
    int main()
    {
    	int connectionFd, in, index = 0, limit = MAX_BUFFER;
    	struct sockaddr_in servaddr;
    	char timebuffer[MAX_BUFFER];
    	
    	connectionFd = socket(AF_INET, SOCK_STREAM, 0);
    	
    	
    	printf("socket id %d\n", connectionFd);
    	memset(&servaddr, 0, sizeof(servaddr));
    	servaddr.sin_family = AF_INET;
    	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    	servaddr.sin_port = htons(2214);
    	
    
    
    	pthread_t hThread;
    
    	if ( -1 == connect(connectionFd, (struct sockaddr*) &servaddr, sizeof(servaddr)) ) {
    		printf("Failed to connect.\n");
    		return 0;
    	}
    
    	pthread_create(&hThread, 0, secondThread, &connectionFd);
    
    	fd_set testset;
    	FD_ZERO(&testset);
    	FD_SET(connectionFd, &testset);
    	
    
    	int status;
    
    	while (1) {
    	if (0 == pthread_join(hThread, (void **)&status)) {
    		break;
    	}
    	}
    	close(connectionFd);
    	
    	return 0;
    }
    Server program:
    Code:
    #include <sys/types.h>
    #include <sys/time.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <poll.h>
    #include <string.h>
    
    int main()
    {
    	char buffer[128];
    	int result, nread, sd, clientsd=-1, nclientlen;
    	struct sockaddr_in addr, clientaddr;
    	
    	sd = socket(AF_INET, SOCK_STREAM, 0);
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(2214);
    	addr.sin_addr.s_addr = htonl(INADDR_ANY);
    	
    	bind(sd, (struct sockaddr*) &addr, sizeof(addr));
    	listen(sd, 5);
    	
    	struct pollfd fds[100];
    	nfds_t nfds = 0;
    	fds[nfds].fd = 0;
    	fds[nfds].events = POLLIN;
    	nfds++;
    	fds[nfds].fd = sd;
    	fds[nfds].events = POLLIN;
    	nfds++;
    	
    	
    	while(1){
    		result = poll(fds, nfds, -1);
    		printf(". ");
    		switch(result) {
    			case 0:
    			printf("timeout\n");
    			break;
    			case -1:
    			printf("select");
    			break;
    			default:
    			if (fds[1].revents & POLLIN) {
    				nclientlen = sizeof(clientaddr);
    				
     				clientsd = accept(sd, (struct sockaddr*) &clientaddr, &nclientlen);
    			}
    			if (fds[0].revents & POLLIN) {
    				ioctl(0, FIONREAD, &nread);				
    				if (0 == nread) {
    					printf("keyboard done.\n");
    				} else {
    					nread = read(0, buffer, nread);
    					buffer[nread-1] = 0;
    					if (strcmp(buffer, "close") == 0) {
    						if (-1 != clientsd ) {
    							printf("close client socket.\n");
    						close(clientsd);
    						clientsd = -1;
    						}
    					} else 	if (-1 != clientsd) {
    					write(clientsd, buffer, nread);
    					printf("send %s to client.\n", buffer);
    					} 
    				}
    			}
    			break;
    		}
    	}
    }

  2. #2
    Registered User
    Join Date
    Dec 2006
    Posts
    2
    Can anyone help me?

  3. #3
    Registered User
    Join Date
    Apr 2007
    Posts
    51
    Bump on this. I am having the same issue. I get a POLLIN rather than POLLHUP. The code is very similar to what was posted and is pretty straight forward sockets, nothing trick yet.

    I issued close() on the server side, I even powered down the server after, and the client still shows POLLIN vs POLLHUP..


    Anyone?

    Edit: I found some more info, it it seems as though the POLLHUP will only be triggered by a close in the write direction on the locla side. So me closing the remote side, most likely will not trigger it...

    If anyone has insite on this, please feel free to add..
    Last edited by markcole; 04-26-2007 at 01:37 PM. Reason: Additional info

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by markcole View Post
    Edit: I found some more info, it it seems as though the POLLHUP will only be triggered by a close in the write direction on the locla side. So me closing the remote side, most likely will not trigger it...
    Correct. To detect it the other direction, look if recv() returned 0 even when POLLIN was set. That's how you detect a remote-side disconnect -- a blocking call to recv() returns a count of 0. POLLIN is just telling you that recv() is capable of giving you useful status (i.e., won't block), it doesn't mean there's data there.
    Last edited by brewbuck; 04-26-2007 at 10:03 PM.

  5. #5
    Registered User
    Join Date
    Apr 2007
    Posts
    51
    Quote Originally Posted by brewbuck View Post
    Correct. To detect it the other direction, look if recv() returned 0 even when POLLIN was set. That's how you detect a remote-side disconnect -- a blocking call to recv() returns a count of 0. POLLIN is just telling you that recv() is capable of giving you useful status (i.e., won't block), it doesn't mean there's data there.
    Thanks for the final push, I was headed in that direction, but was hung up so to speak.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by markcole View Post
    Thanks for the final push, I was headed in that direction, but was hung up so to speak.
    That ones a groaner

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lame null append cause buffer to crash
    By cmoo in forum C Programming
    Replies: 8
    Last Post: 12-29-2008, 03:27 AM
  2. Thread Prog in C language (seg fault)
    By kumars in forum C Programming
    Replies: 22
    Last Post: 10-09-2008, 01:17 PM
  3. Actors, cues, event based logic.
    By Shamino in forum Game Programming
    Replies: 2
    Last Post: 04-27-2006, 10:58 PM
  4. XWindows- Close window event?
    By Exile in forum Linux Programming
    Replies: 8
    Last Post: 01-09-2005, 10:39 PM