Skip site navigation (1)Skip section navigation (2)
Date:      Fri,  9 Nov 2001 08:00:42 +1100 (EST)
From:      Andrew <andrew@ugh.net.au>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/31860: read wont timeout on sockets if using threads
Message-ID:  <20011108210042.4504BA842@starbug.ugh.net.au>

next in thread | raw e-mail | index | archive | help


>Number:         31860
>Category:       bin
>Synopsis:       read wont timeout on sockets if using threads
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 08 13:10:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Andrew
>Release:        FreeBSD 4.4-STABLE i386
>Organization:
UgH!
>Environment:
System: FreeBSD starbug.ugh.net.au 4.4-STABLE FreeBSD 4.4-STABLE #3: Sun Oct 7 21:30:09 EST 2001 andrew@starbug.ugh.net.au:/usr/obj/usr/src/sys/STARBUG i386


	
>Description:

I have a program that creates a TCP socket and listens for incoming
connections. After calling accept it uses setsockopt and the SO_RCVTIMEO and
SO_SNDTIMEO options so that reads will timeout if no data is received for a
while.

This works flawlessly unless the program is compiled with -pthread (the
program doesn't actually use any pthread_* functions). If compiled with
threads then a call to read will block forever.

>How-To-Repeat:

This is an example program that works as expected unless -pthread is passed
to the compiler (as expected means read times out after 15 seconds). You
can also get this program from http://www.ugh.net.au/~andrew/tmp/setsockopt.c
in case it gets mangled in transit.


#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
	char buffer[1024];
	int listening_fd,
		connection_fd,
		port,
		size;
	struct sockaddr_in local_address,
						remote_address;
	struct timeval tv;

	if (argc != 2) {
		fprintf(stderr, "usage: %s port\n", getprogname());
		exit(1);
	} else {
		port = atoi(argv[1]);
	}

	/* create socket */
	if ((listening_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
		err(1, "socket");
	}

	/* allow us to rebind even if old clients are still hanging around */
	size = 1; /* borrow memory for a second */
	if (setsockopt(listening_fd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size)) != 0) {
		err(1, "setsockopt");
	}

	/* describe our end of the connection */
	bzero(&local_address, sizeof(local_address));
	local_address.sin_family = AF_INET;
	local_address.sin_addr.s_addr = htonl(INADDR_ANY);
	local_address.sin_port = htons(port);

	/* bind the socket to the address */
	if (bind(listening_fd, (struct sockaddr *)&local_address, sizeof(local_address)) == -1) {
		err(1, "bind");
	}

	/* make it a listening port */
	if (listen(listening_fd, -1) != 0) {
		err(1, "listen");
	}

	/* accept connections */
	for (;;) {
		size = sizeof(remote_address);
		if ((connection_fd = accept(listening_fd, (struct sockaddr *)&remote_address, &size)) == -1) {
			err(1, "accept");
		}

		printf("connected...\n");

		/* set up timeouts */
		tv.tv_sec = 15L;
		tv.tv_usec = 0L;
		if (setsockopt(connection_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
			err(1, "setsockopt");
		}
		if (setsockopt(connection_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
			err(1, "setsockopt");
		}

		/* do a bit of reading and writing */
#define STRING "hello\n"
		if (write(connection_fd, STRING, sizeof(STRING)) == -1) {
			err(1, "write");
		}
#undef STRING

		if (read(connection_fd, buffer, sizeof(buffer)) == -1) {
			warn("read");
			goto failure;
		} else {
			printf("received %s", buffer);
		}

#define STRING "goodbye\n"
		if (write(connection_fd, STRING, sizeof(STRING)) == -1) {
			err(1, "write");
		}
#undef STRING

failure:
		if (close(connection_fd) == -1) {
			err(1, "close");
		}

		printf("disconnected...\n");
	}

	return 0;
}	

>Fix:

	
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011108210042.4504BA842>