Date: Sun, 17 Dec 1995 02:52:29 +1100 From: danjo@blitzen.canberra.edu.au To: FreeBSD-gnats-submit@freebsd.org Subject: misc/898: bug? Message-ID: <199512161552.CAA05399@eyerot.canberra.edu.au> Resent-Message-ID: <199512170920.BAA09845@freefall.freebsd.org>
index | next in thread | raw e-mail
>Number: 898
>Category: misc
>Synopsis: select() not detecting socket close under certain circumstances
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Dec 17 01:20:06 PST 1995
>Last-Modified:
>Originator: Danny Gasparovski
>Organization:
>Release: FreeBSD 2.1-STABLE i386
>Environment:
Running 2.1 RELEASE, no idea if other releases are affected
>Description:
If a process opens a socket, sheds it's controlling terminal, then closes the socket, the other end will not (with select()) detect that the socket has closed.
>How-To-Repeat:
Here is the source of a test program, t1.c:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
extern int errno;
#undef SPAM
main()
{
struct sockaddr_in addr;
int addrlen = sizeof(addr);
int s;
s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(6666);
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
fprintf(stderr, "bind() failed: %s\n", strerror(errno));
exit(1);
}
listen(s, 1);
s = accept(s, (struct sockaddr *)&addr, &addrlen);
sleep(5);
#ifdef SPAM
if (fork())
exit(0);
setsid();
if (fork()) {
wait(&s);
exit(0);
}
setpgid(0, 0);
#endif
close(s); /* t2 should exit now */
sleep(5);
exit(0);
}
Here is the source of t2.c:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/in.h>
main()
{
struct sockaddr_in addr;
fd_set r;
int s;
char *buf[256];
time_t t;
time(&t);
s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6666);
connect(s, (struct sockaddr *)&addr, sizeof(addr));
while (1) {
FD_ZERO(&r);
FD_SET(s, &r);
select(s+1, &r, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
if (FD_ISSET(s, &r)) {
if (read(s, buf, 256) == 0) {
fprintf(stderr, "Time difference: %d\n", time((time_t *)0) - t);
exit(0);
}
}
}
}
Now, if you undefine SPAM in t1.c and compile/run it, then compile/run t2.c, t2 should exit when t1 does a close() on the socket. However, if you #define SPAM in t1.c, compile/run it, and then run t2, t2 will NOT exit when t1 issues the close() on the socket.
With SPAM undefined, t2 will report a 5 second wait, with SPAM defined it will report a 10 second wait.
>Fix:
I have no idea.
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199512161552.CAA05399>
