Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Aug 2002 16:55:13 -0700 (PDT)
From:      Archie Cobbs <archie@packetdesign.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/42100: libc_r: accept(2) can't handle descriptor being closed/shutdown
Message-ID:  <200208272355.g7RNtDT18751@bubba.packetdesign.com>

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

>Number:         42100
>Category:       bin
>Synopsis:       libc_r: accept(2) can't handle descriptor being closed/shutdown
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 27 17:10:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Archie Cobbs
>Release:        FreeBSD 4.6-stable i386
>Organization:
Packet Design
>Environment:

FreeBSD stable.packetdesign.com 4.6-STABLE FreeBSD 4.6-STABLE #0: Tue Aug 20 20:36:49 PDT 2002     archie@stable.packetdesign.com:/usr/obj/usr/src/sys/STABLE  i386

>Description:

	The program below behaves differently when linked with "-pthread"
	vs. when linked with the normal libc.

	If you run the program, then hit control-C. This will cause the
	socket to be either close(2)'d or shutdown(2) (one is randomly
	chosen).

	When linked with libc, the accept() call immediately returns
	with an error. But when linked with libc_r, the accept() call
	never returns (in either the close() or shutdown() cases).

	FYI, on RedHat Linux 7.3, the program always exits even if linked
	with '-lpthread' for both the close() and shutdown() cases.

	The same libc_r behavior happens if you compile with the
	'-DSIGNAL_TEST=0' flag, which uses a separate thread to
	close the socket.

	I'd suspect that other blocking I/O calls besides accept(2)
	have this same problem.

>How-To-Repeat:

	Save the program below as 'xx.c' and compile with libc:

		$ cc -Wall -o xx xx.c

	Start the program, then press control-c. Notice that it always
	terminates immediately:

		$ ./xx
		main: waiting for connection...
		^Csignal_handler: rec'd signal 2...
		signal_handler: shutdown()'ing socket...
		xx: main: accept: Software caused connection abort
		$ ./xx
		main: waiting for connection...
		^Csignal_handler: rec'd signal 2...
		signal_handler: close()'ing socket...
		xx: main: accept: Bad file descriptor
		$

	Now compile the program with the '-pthread' flag:

		$ cc -Wall -o xx xx.c -pthread -D_THREAD_SAFE

	Now notice that the program never terminates after
	(the first time) control-C is pressed:

		$ ./xx
		main: waiting for connection...
		^Csignal_handler: rec'd signal 2...
		signal_handler: shutdown()'ing socket...

	Also, occasionally when running the '-pthread' version you'll
	get this core dump after two control-C presses:

		$ ./xx
		main: waiting for connection...
		^Csignal_handler: rec'd signal 2...
		signal_handler: shutdown()'ing socket...
		^Csignal_handler: rec'd signal 2...
		signal_handler: close()'ing socket...
		Segmentation fault(core dumped)

	Here's the stack trace and reason for the segfault:

Core was generated by `xx'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libc_r.so.4...done.
Reading symbols from /usr/libexec/ld-elf.so.1...done.
(gdb) where
#0  0x280a64ba in _accept (fd=5, name=0xbfbff738, namelen=0xbfbff734)
    at /usr/src/lib/libc_r/uthread/uthread_accept.c:53
#1  0x8048866 in main ()
#2  0x80486d1 in _start ()
(gdb) list
48              /* Lock the file descriptor: */
49              if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) {
50                      /* Enter a loop to wait for a connection request: */
51                      while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
52                              /* Check if the socket is to block: */
53                              if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
54                                      /* Save the socket file descriptor: */
55                                      _thread_run->data.fd.fd = fd;
56                                      _thread_run->data.fd.fname = __FILE__;
57                                      _thread_run->data.fd.branch = __LINE__;
(gdb) p _thread_fd_table
$1 = (struct fd_table_entry **) 0x8058000
(gdb) p fd
$2 = 5
(gdb) p _thread_fd_table[5]
$3 = (struct fd_table_entry *) 0x0

>Fix:


>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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