LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
 
Search this Thread
Old 02-25-2014, 02:29 AM   #1
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 149

Rep: Reputation: 17
Unhappy Socket program and fork()


Hi, I'm puzzled with the piece of code. It is a TCP server program that is supposed to handle multiple incoming connections. First I tried without FORKING and the outcome was expected: When the function some_connection_handler() exits, the client knows immediately about the disconnection.

But when I tried with FORKING, and when some_connection_handler() exited, the client didn't know. What is wrong?

Error checking skipped for easier reading..
Code:
// ...

//Create socket
int servSock = socket( PF_INET, SOCK_STREAM, 0 );

//Set non-blocking
int n = fcntl( servSock, F_GETFL );
fcntl( servSock, F_SETFL, n | O_NONBLOCK );

//Set socket options
int opt = 1;
setsockopt( servSock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt) );
setsockopt( servSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );

//Fill in the address of the server ip and port
struct sockaddr_in servAddr;
memset( &servAddr, 0, sizeof(servAddr) );
// ... some details skipped ...
servAddr.sin_family = AF_INET;

bind( servSock, (struct sockaddr *)&servAddr, sizeof(servAddr) );
listen( servSock, SOMAXCONN );

fd_set rfds;
struct timeval tv;
int retval;

tv.tv_sec = 0;
tv.tv_usec = 100;

while (1) {
	FD_ZERO(&rfds);
	FD_SET(servSock, &rfds);
	retval = select( servSock+1, &rfds, NULL, NULL, &tv );
	if (retval == -1) {
		perror("select()");
		break;
	}
	else if (retval && FD_ISSET(servSock, &rfds)) {

		int clntSock = accept( servSock, (struct sockaddr *)NULL, NULL );

#ifdef FORKING
		pid_t pid = fork();
		if (pid == -1) {
			perror( "fork()" );
			break;
		}
		else if (pid == 0) {
			some_connection_handler( clntSock );
			close( clntSock );
			break;
		}
#else
		some_connection_handler( clntSock );
		close( clntSock );
#endif
	}
	else {
		if (some_quit_condition()) break;
	}
}//while(1)
close( servSock );

//...
 
Old 02-25-2014, 02:44 AM   #2
pan64
Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 5,835

Rep: Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529Reputation: 1529
I think you need to check the return code of the child process.
Code:
if ( pid == -1 ) # error case
if ( pid == 0 ) # child process
if ( pid > 0 ) # parent process
# missing 
{ wait for pid }
# see man wait
 
Old 02-25-2014, 03:11 AM   #3
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 149

Original Poster
Rep: Reputation: 17
Red face

I think I found the answer - both the parent and child instance should close the clntSock, as:
Code:
#ifdef FORKING
		pid_t pid = fork();
		if (pid == -1) {
			perror( "fork()" );
			break;
		}
		else if (pid == 0) {
			some_connection_handler( clntSock );
			close( clntSock );
			break;
		}
		else {
			close( clntSock );  // could write this block of if-code better.
		}
#else
		some_connection_handler( clntSock );
		close( clntSock );
#endif
will look up wait. Thanks.
 
Old 02-25-2014, 09:42 PM   #4
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 149

Original Poster
Rep: Reputation: 17
To make this post complete for future readers, I have revised the code to:
Code:
//Create socket
int servSock = socket( PF_INET, SOCK_STREAM, 0 );

//Set non-blocking
int n = fcntl( servSock, F_GETFL );
fcntl( servSock, F_SETFL, n | O_NONBLOCK );

//Set socket options
int opt = 1;
setsockopt( servSock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt) );
setsockopt( servSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );

//Fill in the address of the server ip and port
struct sockaddr_in servAddr;
memset( &servAddr, 0, sizeof(servAddr) );
// ... some details skipped ...
servAddr.sin_family = AF_INET;

bind( servSock, (struct sockaddr *)&servAddr, sizeof(servAddr) );
listen( servSock, SOMAXCONN );

fd_set rfds;
struct timeval tv;
int retval;

tv.tv_sec = 0;
tv.tv_usec = 100;

while (1) {
	FD_ZERO(&rfds);
	FD_SET(servSock, &rfds);
	retval = select( servSock+1, &rfds, NULL, NULL, &tv );
	if (retval == -1) {
		perror( "select()" );
		break;
	}
	else if (retval && FD_ISSET(servSock, &rfds)) {

		int clntSock = accept( servSock, (struct sockaddr *)NULL, NULL );

		pid_t pid = fork();
		if (pid == -1) {
			perror( "fork()" );
			break;
		}
		else if (pid == 0) {
			some_connection_handler( clntSock );
			close( clntSock );
			break;
		}
		else {
			close( clntSock );
		}
	}
	else {
		if (some_quit_condition()) break;
	}
	waitpid( -1, NULL, WNOHANG );
}//while(1)
waitpid( -1, NULL, 0 ); // or wait( NULL )
close( servSock );
 
  


Reply

Tags
fork, tcp


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
program to listen on TCP socket and start some program with I/O redirected to socket leniviy Linux - Software 4 08-12-2013 05:51 AM
fork()'ed or multi threaded socket I/O? thedevilsjester Programming 5 09-24-2008 12:41 AM
how to implement fork() in socket programming b/w server/client in voice communicatio timeout4me Programming 1 08-05-2005 04:01 PM
C: Socket weirdness: select() -> fork() -> accept() maxfacta Programming 1 03-01-2005 01:33 PM
How to fork a program and tell when it's done? tonyfreeman Programming 5 09-01-2004 10:25 PM


All times are GMT -5. The time now is 08:47 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration