Threaded socket hang in 1.3.20

Jason Tishler jason@tishler.net
Tue Feb 18 22:20:00 GMT 2003


While running the Python regression test to verify my rebase package
before release, I stumbled across a hang in 1.3.20-1 (and CVS) when
socket() is called from one thread after accept() has been called in
another.

This problem has recently been discussed in the following Cygwin mailing
thread:

    http://cygwin.com/ml/cygwin/2003-02/msg01341.html
    http://cygwin.com/ml/cygwin/2003-02/msg01350.html

The problem was introduced sometime after 1.3.19-1 and before
2003-Feb-01 snapshot.

The attached C++ testcase demonstrates the problem.  In 1.3.20-1, the
program hangs in the call to socket() in the second thread:

    Creating thread for fn1
    fn1 begin
    fn1: calling accept()...
    Creating thread for fn2
    fn2 begin
    fn2: calling socket()...

While in 1.3.19-1, we get the following:

    Creating thread for fn1
    fn1 begin
    fn1: calling accept()...
    Creating thread for fn2
    fn2 begin
    fn2: calling socket()...
    fn2: socket() returned
    fn2: calling connect()...
    fn2: connect returned
    fn2: connect() failed with 111

I'm not sure why connect() fails, because a "telnet localhost 54321"
works just fine.  I'm probably demonstrating my sockets ignorance.

I will try to dig deeper, but I'm hoping that maybe a light bulb will go
on in the meantime.

BTW, does anyone have any snapshots after 1.3.19-1, but before
2003-Feb-01?  If so, please (privately) mail them to me or post a URL.

Thanks,
Jason

-- 
PGP/GPG Key: http://www.tishler.net/jason/pubkey.asc or key servers
Fingerprint: 7A73 1405 7F2B E669 C19D  8784 1AFD E4CC ECF4 8EF6
-------------- next part --------------
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/errno.h>

#define PORT 54321

void*
fn1(void *id)
{
	printf("fn1 begin\n");

	int s = socket(AF_INET, SOCK_STREAM, 0);
	if (s < 0)
	{
		printf("fn1: socket() failed with %d\n", errno);
		pthread_exit(0);
	}

	struct sockaddr_in lsocket;
	memset(&lsocket, 0, sizeof(lsocket));
	lsocket.sin_family = AF_INET;
	lsocket.sin_addr.s_addr = INADDR_ANY;
	lsocket.sin_port = htons(PORT);

	int status = bind(s, (struct sockaddr*) &lsocket, sizeof(lsocket));
	if (status < 0)
	{
		printf("fn1: bind() failed with %d\n", errno);
		pthread_exit(0);
	}

	status = listen(s, 5);
	if (status < 0)
	{
		printf("fn1: listen() failed with %d\n", errno);
		pthread_exit(0);
	}

	struct sockaddr_in fromAddr;
	socklen_t fromAddrLen = sizeof(fromAddr);
	printf("fn1: calling accept()...\n");
	status = accept(s, (struct sockaddr*) &fromAddr, &fromAddrLen);
	printf("fn1: accept returned\n");

	printf("fn1 end\n");
	pthread_exit(0);
}

void*
fn2(void *id)
{
	printf("fn2 begin\n");

	printf("fn2: calling socket()...\n");
	int s = socket(AF_INET, SOCK_STREAM, 0);
	printf("fn2: socket() returned\n");
	if (s < 0)
	{
		printf("fn1: socket() failed with %d\n", errno);
		pthread_exit(0);
	}

	struct sockaddr_in lsocket;
	memset(&lsocket, 0, sizeof(lsocket));
	lsocket.sin_family = AF_INET;
	lsocket.sin_addr.s_addr = INADDR_LOOPBACK;
	lsocket.sin_port = htons(PORT);

	printf("fn2: calling connect()...\n");
	int status = connect(s, (struct sockaddr*) &lsocket, sizeof(lsocket));
	printf("fn2: connect returned\n");
	if (status < 0)
	{
		printf("fn2: connect() failed with %d\n", errno);
		pthread_exit(0);
	}

	printf("fn2 end\n");
	pthread_exit(0);
}

int
main(int argc, char *argv[])
{
	pthread_t thread;

	printf("Creating thread for fn1\n");
	int rc = pthread_create(&thread, 0, fn1, 0);
	if (rc)
	{
		printf("ERROR: return code from pthread_create() is %d\n", rc);
		exit(-1);
	}

	sleep(1);

	printf("Creating thread for fn2\n");
	rc = pthread_create(&thread, 0, fn2, 0);
	if (rc)
	{
		printf("ERROR: return code from pthread_create() is %d\n", rc);
		exit(-1);
	}

	pthread_exit(0);
}


More information about the Cygwin-developers mailing list