Hello everyone,

I'm developing a multi-client server on Linux and I've noticed a strange behavior: I'm using a regular Makefile to compile and run my server, nothing fancy. But now I've tried to run my server by hand using the command line and my server won't accept any incoming connections ! In other word: there isn't any problem problem when I launch it from "make run" and there is one only If I do "./build/debug/main" (see the Makefile).

A little description of my program is required to understand where the problem could be. It is made of a main thread which creates an Server instance and the socket of the server. Then it creates a pthread (listening thread) with the passed server socket fd. It should share the same socket (same integer value) as in the main thread.

The goal of the main thread is to wait for some data on any socket (via epoll_wait). The goal of the listening thread is to accept any incoming connections, to queue it in epoll for the main then wait again.
I tested to copy the code of the listening thread in the main one (for this test I removed the pthread_create of course) and it was working without any error.

The error happens (when launching by hand) in the listening thread when it accepts on the main socket because it returns -1.
So it seems that the pthread doesn't share the main thread socket _only_ when it is ran by hand ! What does the Makefile and how could it modify the behavior of sockets with pthread ?! I need some help because I don't have any clue about this behavior.

Makefile : http://pastebin.com/QFerjewd (posted outside not to overload the topic)

Main thread :

int i = 1;
	
	// Init a socket
	_socket = socket(family, type, protocol); // it's: AF_INET, SOCK_STREAM, 0
	if (_socket < 0)
		Globals::Log(LOGGER_TYPE_FATAL, LOGGER_CAT_NETWORK, true, "ERROR opening socket");
	
	// Server socket struct
	bzero((char *) &_serv_addr, sizeof(_serv_addr));
	_serv_addr.sin_family = AF_INET;
	_serv_addr.sin_addr.s_addr = INADDR_ANY;
	_serv_addr.sin_port = htons(port); // it's: 2055
	memset(&_serv_addr.sin_zero, 0, 8); // zero the rest
	setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
	
	// Epoll
	_epoll_clients = epoll_create(SERVER_MAX_CLIENTS);
	if (_epoll_clients < 0)
		Globals::Log(LOGGER_TYPE_FATAL, LOGGER_CAT_NETWORK, true, "ERROR while creating epoll");
	
	// Create the listener
	_listener = new SocketServerListener(this, _socket); // Give the socket to the listening thread (it's a integer !)

	if (bind(_socket, (struct sockaddr *) &_serv_addr, sizeof(_serv_addr)) < 0) 
		Globals::Log(LOGGER_TYPE_FATAL, LOGGER_CAT_NETWORK, true, "ERROR on binding");
		
	listen(_socket, SERVER_QUEUE_MAX);
	_listener->Start(NULL); // <-- pthread_create (Listening Thread -> code below)
	OnStart();
	WaitEpoll();

Listening Thread:

while (Continue()) {
		int socket;
		struct sockaddr_in addr;
		socklen_t len;
		
		#ifdef DEBUG
		Globals::Log(LOGGER_TYPE_DEBUG, LOGGER_CAT_NETWORK, false, "[SSL Thread]: Waiting for clients.");
		#endif
		
		/* always returns -1 when launching by hand 
		 * so the error below is printed out and client is disconnected
		 */
		socket = accept(_socket, (struct sockaddr *) &addr, &len);
		if (socket < 0) {
			Globals::Log(LOGGER_TYPE_ERROR, LOGGER_CAT_NETWORK, false, "[SSL Thread]: Invalid socket %i (%s)", 
					socket, strerror(errno));
			continue;
		}
		#ifdef DEBUG
		Globals::Log(LOGGER_TYPE_DEBUG, LOGGER_CAT_NETWORK, false, "[SSL Thread]: Accepted a new client on %i", socket);
		#endif
		
		// Send to the parent
		_parent->OnConnect(socket);
	}

in Listening Thread the 2nd parameter of accept(), addr, wasn't set causing the system call to return invalid argument. How to fix:

memset(&addr, 0, sizeof(struct sockaddr_in))
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.