Skip site navigation (1)Skip section navigation (2)
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>

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

>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:



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