Subject: bin/15174: gdb "kill" command does not free sockets
To: None <gnats-bugs@gnats.netbsd.org>
From: None <gson@nominum.com>
List: netbsd-bugs
Date: 01/07/2002 19:03:48
>Number:         15174
>Category:       bin
>Synopsis:       gdb "kill" command does not free sockets
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jan 07 19:05:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Andreas Gustafsson
>Release:        NetBSD 1.5Z
>Organization:
Nominum Inc
>Environment:
System: NetBSD guava.araneus.fi 1.5Z NetBSD 1.5Z (GUAVA) #0: Sat Dec 15 20:49:20 PST 2001 gson@guava.araneus.fi:/usr/src/sys/arch/i386/compile/GUAVA i386
Architecture: i386
Machine: i386
>Description:

When using gdb to debug a program that listens on one or more sockets,
killing the program using the gdb "kill" command does not cause the
sockets to be fully freed as they would be if the process exited.  If
the program is then restarted using the "run" command, it will be
unable to bind to the sockets as they are "already in use".  This
makes debugging network daemons under NetBSD awkward.

This bug affects at least NetBSD 1.4 and 1.5, on i386 and sparc.
It does not matter whether the SO_REUSEADDR socket option is set.

On other operating systems, gdb does *not* exhibit this behavior.

>How-To-Repeat:

    $ cat test.c
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <err.h>

    main() {
	    int s, r;
	    struct sockaddr_in local;
	    struct sockaddr_in remote;
	    socklen_t len;

	    memset(&local, 0, sizeof local);
	    local.sin_port = htons(5555);

	    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	    if (s < 0)
		    err(1, "socket");
	    r = bind(s, (struct sockaddr *) &local, sizeof local);
	    if (r < 0)
		    err(1, "bind");
	    r = listen(s, 5);
	    if (r < 0)
		    err(1, "listen");
	    accept(s, (struct sockaddr *) &remote, &len);
    }
    $ cc -g test.c
    $ gdb a.out
    GNU gdb 5.0-nb1
    Copyright 2000 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i386-unknown-netbsdelf"...
    (gdb) run
    Starting program: /usr/s/u/gson/bugs/netbsd/gdb.kill/a.out 
    ^C
    Program received signal SIGINT, Interrupt.
    0x480aa2ab in accept () from /usr/lib/libc.so.12
    (gdb) kill
    Kill the program being debugged? (y or n) y
    (gdb) run
    Starting program: /usr/s/u/gson/bugs/netbsd/gdb.kill/a.out 
    a.out: bind: Address already in use

    Program exited with code 01.
    (gdb)

>Fix:

Unknown.  As a workaround, use the gdb commands "signal SIGKILL"
and "continue" instead of "kill". 
>Release-Note:
>Audit-Trail:
>Unformatted: