public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Michael Lindner <mikel@att.net>
To: Chris Wedgwood <cw@f00f.org>
Cc: Dan Maas <dmaas@dcine.com>, linux-kernel@vger.kernel.org
Subject: Re: PROBLEM: select() on TCP socket sleeps for 1 tick even if data  available
Date: Sat, 20 Jan 2001 02:46:28 -0500	[thread overview]
Message-ID: <3A694254.B52AE20B@att.net> (raw)
In-Reply-To: <fa.nc2eokv.1dj8r80@ifi.uio.no> <fa.dcei62v.1s5scos@ifi.uio.no> <015e01c082ac$4bf9c5e0$0701a8c0@morph> <3A69361F.EBBE76AA@att.net> <20010120200727.A1069@metastasis.f00f.org>

[-- Attachment #1: Type: text/plain, Size: 809 bytes --]

Chris Wedgwood wrote:
> 
> You can measure this latency; and it's indeed very low (lmbench gives
> 28 usecs on one of my machines).
> 
> If you don't see this I would suspect an application bug -- can you
> use strace or some such and confirm this is not the case?

OK, two new data points (thanks for staying with me here):

1. The problem only occurs when traffic is travelling over DIFFERENT
sockets (i.e. A->B->C->D... or A->B->A but using a separate socket for
traffic in each direction).

2. I wrote a very ugly program (attached) to reproduce the problem. Lest
you think ill of me, most of this isn't actual code I wrote (the actual
program that first reproduced the problem was in C++). Just run

	sockperf localhost 54321 54322
	sockperf localhost 54322 54321 1

to see it in action.

--
Mike Lindner

[-- Attachment #2: sockperf.c --]
[-- Type: text/plain, Size: 5007 bytes --]

#include <fcntl.h>
#include <memory.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <varargs.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>


#ifndef INADDR_NONE
#define INADDR_NONE	~0
#endif

void
errexit(format, va_alist)
char	*format;
va_dcl
{
	va_list	args;
	va_start(args);
	vfprintf(stderr, format, args);
	va_end(args);
	exit(1);
}

/*
 * passivesock - allocate & bind a server socket using TCP or UDP
 */

int
passivesock( service, protocol, qlen )
char	*service;	/* service associeted with the desired port	*/
char	*protocol;	/* name of protocol to use ("tcp" or "udp")	*/
int	qlen;		/* maximum length of the server request queue	*/
{
	struct servent *pse;
	struct protoent *ppe;
	struct sockaddr_in sin;
	int	s, type;
	int	one = 1;

	bzero((char *) & sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;

	/* Map service name to port number */
	if ( pse = getservbyname(service, protocol) )
		sin.sin_port = htons(ntohs((u_short)pse->s_port));
	else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0 )
		errexit("can't get \"%s\" service entry\n", service);

	/* Map protocol name to protocol number */
	if ( (ppe = getprotobyname(protocol)) == 0)
		errexit("can't get \"%s\" protocol entry\n", protocol);

	/* Use protocol to chose a socket type */
	if (strcmp(protocol, "udp") == 0)
		type = SOCK_DGRAM;
	else
		type = SOCK_STREAM;

	/* Allocate a socket */
	s = socket(PF_INET, type, ppe->p_proto);
	if (s < 0 )
		errexit("can't create socket: %s\n", strerror(errno));

	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
	/* Bind the socket */
	if (bind(s, (struct sockaddr *) & sin, sizeof(sin)) < 0)
		errexit("can't bind to %s port: %s\n", service,
		    strerror(errno));
	if (type == SOCK_STREAM && listen(s, qlen) < 0)
		errexit("can't listen on %s port: %s\n", service,
		    strerror(errno));
	return s;
}

int
connectsock(host, service, protocol)
char	*host;
char	*service;
char	*protocol;
{
	struct hostent	*phe;
	struct servent	*pse;
	struct protoent	*ppe;
	struct sockaddr_in	sin;
	int	s, type;

	memset(&sin, 0, sizeof(sin));
	if (pse = getservbyname(service, protocol))
		sin.sin_port = pse->s_port;
	else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
		fprintf(stderr, "can't get '%s' service entry\n", service);
		exit(1);
	}
	if (phe = gethostbyname(host)) 
		memcpy((char *) &sin.sin_addr, phe->h_addr, phe->h_length);
	else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
		fprintf(stderr, "can't get '%s' host entry\n", host);
		exit(1);
	}
	/* if (ppe = getprotobyname(protocol)) {
		fprintf(stderr, "can't get '%s' protocol entry\n", protocol);
		exit(1);
	}
	if (strcmp(protocol, "udp") == 0)
		type = SOCK_DGRAM;
	else
		type = SOCK_STREAM;
	*/
	sin.sin_family = AF_INET;
	s = socket(AF_INET, SOCK_STREAM, 6);
	if (s < 0) {
		perror("can't create socket\n");
		exit(1);
	}
	if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
		perror("can't connect to socket");
		exit(1);
	}
	return s;
}

void
pingpong(int r, int s, int ping)
{
	struct timeval then;
	struct timeval now;
	fd_set fds;
	fd_set readfds;
	int pings = 0;
	FD_ZERO(&fds);
	FD_SET(r, &fds);
	gettimeofday(&then, 0);
	if (ping) {
		send(s, ".", 1, 0);
		pings++;
	}
	readfds = fds;
	while (select(r+1, &readfds, 0, 0, 0) > 0) {
		if (FD_ISSET(r, &readfds)) {
			char buf[1];
			int n = read(r, buf, sizeof(buf));
			if (n <= 0) {
				break;
			}
			else {
				if (pings++ < 1000) {
					send(s, ".", 1, 0);
				}
				else {
					break;
				}
			}
		}
		else {
			fprintf(stderr, "fd not set!\n");
		}
		readfds = fds;
	}
	gettimeofday(&now, 0);
	fprintf(stderr, "elapsed time for 1000 pingpongs is %g\n", now.tv_sec - then.tv_sec + (now.tv_usec - then.tv_usec) / 1000000.0);
	fprintf(stderr, "closing %d\n", r);
	close(r);
	fprintf(stderr, "closing %d\n", s);
	close(s);
}

main(argc, argv)
int	argc;
char	**argv;
{
	char	buf[1024];
	int	n;
	int	s;
	int	f;
	if (argc < 3) {
		errexit("usage: %s host port1 port2 [initiate]\n", argv[0]);
	}
	signal(SIGPIPE, SIG_IGN);
	f = passivesock(argv[2], "tcp", 2);
	if (f < 0) {
		errexit("listen failed: %s\n", strerror(errno));
	}
	for ( ; ; ) {
		struct sockaddr_in	fsin;
		int	alen = sizeof(fsin);
		if (argc < 5) {
			int	r = accept(f, (struct sockaddr *) &fsin, &alen);
			int	s = connectsock(argv[1], argv[3], "tcp");
			if (r < 0)
				errexit("accept failed: %s\n", strerror(errno));
			if (s < 0)
				errexit("connect failed: %s\n", strerror(errno));
			pingpong(r, s, 0);
		}
		else {
			int	s = connectsock(argv[1], argv[3], "tcp");
			int	r = accept(f, (struct sockaddr *) &fsin, &alen);
			if (r < 0)
				errexit("accept failed: %s\n", strerror(errno));
			if (s < 0)
				errexit("connect failed: %s\n", strerror(errno));
			pingpong(r, s, 1);
			break;
		}
	}
	return 0;
}

  reply	other threads:[~2001-01-20  7:42 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <fa.nc2eokv.1dj8r80@ifi.uio.no>
     [not found] ` <fa.dcei62v.1s5scos@ifi.uio.no>
     [not found]   ` <015e01c082ac$4bf9c5e0$0701a8c0@morph>
2001-01-20  6:54     ` PROBLEM: select() on TCP socket sleeps for 1 tick even if data available Michael Lindner
2001-01-20  7:07       ` Chris Wedgwood
2001-01-20  7:46         ` Michael Lindner [this message]
2001-01-20 21:58           ` Edgar Toernig
2001-01-21  0:35             ` Dan Maas
2001-01-21  0:34               ` Chris Wedgwood
2001-01-21  1:22                 ` Michael Lindner
2001-01-21  1:29                   ` David Schwartz
2001-01-21  3:20                 ` Michael Lindner
2001-04-09 14:54                   ` Stephen D. Williams
2001-04-09 19:16                     ` James Antill
2001-04-10 18:29                       ` Stephen D. Williams
2001-04-10 20:25                         ` James Antill
2001-04-11 21:03                           ` Stephen D. Williams
2001-04-12  0:09                             ` James Antill
2001-01-24 20:31                 ` Boris Dragovic
     [not found]         ` <3A694357.1A7C6AAC@att.net>
2001-01-20  9:41           ` Dan Maas
2001-01-20 17:26             ` Michael Lindner
2001-01-24 23:56 Bernd Eckenfels
  -- strict thread matches above, loose matches on Subject: below --
2001-01-20 10:53 Bernd Eckenfels
2001-01-19 20:47 Michael Lindner
2001-01-19 23:20 ` David Schwartz
2001-01-20  2:30   ` Michael Lindner
2001-01-20  3:27     ` David Schwartz
2001-01-20  4:37       ` Michael Lindner
2001-01-20 12:26     ` Martin MaD Douda
2001-01-20 11:39       ` Bjorn Wesen
2001-01-19 23:31 ` Chris Wedgwood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3A694254.B52AE20B@att.net \
    --to=mikel@att.net \
    --cc=cw@f00f.org \
    --cc=dmaas@dcine.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox