Date: Thu, 10 Jul 2003 17:13:49 +0000 From: Ben <freebsdbug@slimyhorror.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/54331: shutdown() on a socket registered in a kqueue locks up the machine (test code attached) Message-ID: <E19aezN-0005iR-00@mail.phlegethon.org> Resent-Message-ID: <200307101720.h6AHK2CV033561@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 54331 >Category: kern >Synopsis: shutdown() on a socket registered in a kqueue locks up the machine (test code attached) >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 Jul 10 10:20:02 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Ben >Release: FreeBSD 5.1-RELEASE i386 >Organization: none >Environment: System: FreeBSD demeter.cam.zeus.com 5.1-RELEASE FreeBSD 5.1-RELEASE #0: Thu Jul 10 16:59:37 BST 2003 root@demeter .cam.zeus.com:/usr/obj/usr/src/sys/GENERIC i386 Also possibly 5.0 as well - but not able to test that now. >Description: When you shutdown( SHUT_RDWR ) a TCP listen socket which has been added into a kqueue for EVFILT_READ events, the entire machine will lock up. No error messages appear in the logs. >How-To-Repeat: The following code will trigger the crash on the machine (5.1-RELEASE/GENERIC, compiled with '-O'. (Other configurations of the kernel seem to have the same problem). The only other FreeBSD box which I have access to is 4.2-RELEASE, and that appears to work fine. I suspect the bug may also be present in 5.0 (similar symptoms occured, but I had not written this test case then). #include <stdio.h> #include <sys/types.h> #include <sys/event.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <string.h> #include <stdlib.h> #include <time.h> int main( int argc, char **argv ) { int queue, sock, i; struct sockaddr_in addr; struct kevent events[ 10 ]; struct timespec ktime; queue = kqueue(); if( queue == -1 ) { perror( "kqueue() failure" ); exit( 1 ); } sock = socket( AF_INET, SOCK_STREAM, 0 ); /* NOTE: None of this bind() and listen() code is necessary for the crash, * I'm including it to show the crash in 'normal operation' */ memset( &addr, 0, sizeof( addr )); addr.sin_family = AF_INET; addr.sin_port = htons( 3456 ); addr.sin_addr.s_addr = INADDR_ANY; if( bind( sock, (struct sockaddr *) &addr, sizeof( addr )) < 0 ) { perror( "bind" ); exit( 1 ); } if( listen( sock, 32 ) < 0 ) { perror( "listen" ); exit( 1 ); } /* Must add the socket to the kqueue for it to crash */ events[ 0 ].ident = sock; events[ 0 ].udata = 0; events[ 0 ].filter = EVFILT_READ; events[ 0 ].flags = EV_ADD; ktime.tv_sec = 1; ktime.tv_nsec = 0; i = kevent( queue, events, 1, events, 10, &ktime ); printf( "kevent() returned %d\n", i ); printf( "Closing socket\n" ); /* CRASH!!! Must be a shutdown() call, close() alone won't do it. */ shutdown( sock, SHUT_RDWR ); close( sock ); /* Cleanup if we survive */ printf( "Closing queue\n" ); close( queue ); return 0; } >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E19aezN-0005iR-00>