Date: Wed, 28 Aug 2002 10:20:04 -0700 (PDT) From: Daniel Eischen <eischen@pcnet1.pcnet.com> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/42100: libc_r: accept(2) can't handle descriptor being closed/shutdown Message-ID: <200208281720.g7SHK4xA015629@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/42100; it has been noted by GNATS.
From: Daniel Eischen <eischen@pcnet1.pcnet.com>
To: archie@packetdesign.com
Cc:
Subject: Re: bin/42100: libc_r: accept(2) can't handle descriptor being closed/shutdown
Date: Wed, 28 Aug 2002 10:08:40 -0400
I hacked up your program a bit and it looks like the kernel
isn't doing the right thing for accept() on a closed file
descriptor. If you take a look at lib/libc_r/uthread_accept.c,
you'll see that it loops:
while ((ret = __sys_accept(fd, name, namelen)) < 0) {
/* Check if the socket is to block: */
if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0
&& (errno == EWOULDBLOCK || errno == EAGAIN)) {
/* Save the socket file descriptor: */
curthread->data.fd.fd = fd;
curthread->data.fd.fname = __FILE__;
curthread->data.fd.branch = __LINE__;
[...]
waiting for errno to be something other than EWOULDBLOCK or
EAGAIN. So I modified your test program to mimic what libc_r
was doing. The kernel seems to ignore the fact that the
file is closed and always returns EAGAIN. I would expect
EBADF or something.
--
Dan Eischen
/* Set to "1" to abort on signal, or "0" for thread-based delayed abort */
#ifndef SIGNAL_TEST
#define SIGNAL_TEST 1
#endif
#ifdef __linux__
#define _XOPEN_SOURCE 600
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#define _ISOC99_SOURCE 1
#endif
#include <sys/types.h>
#define accept __sys_accept
#include <sys/socket.h>
#undef accept
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#define poll __sys_poll
#include <poll.h>
#undef poll
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <err.h>
#if SIGNAL_TEST
static void signal_handler(int sig);
#else
#include <pthread.h>
static void *thread_entry(void *arg);
static pthread_t tid;
#endif
static int sock;
int
main(int ac, char **av)
{
struct sockaddr_in sin;
socklen_t slen;
struct pollfd fds;
int flags;
int ret;
/* Create socket */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
err(1, "socket");
memset(&sin, 0, sizeof(sin));
#ifndef __linux__
sin.sin_len = sizeof(sin);
#endif
sin.sin_family = AF_INET;
if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
err(1, "socket");
slen = sizeof(sin);
if (listen(sock, 10) == -1)
err(1, "listen");
/* Set non-blocking. */
if ((flags = fcntl(sock, F_GETFL, 0) < 0))
err(1, "fcntl");
flags |= O_NONBLOCK;
if (fcntl(sock, F_SETFL, flags) < 0)
err(1, "fcntl");
#if SIGNAL_TEST
/* Register signal handler */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#else
/* Spawn thread */
if ((errno = pthread_create(&tid, NULL, thread_entry, NULL)) != 0)
err(1, "pthread_create");
#endif
/* Listen for connections on socket */
printf("main: waiting for connection...\n");
while (((ret = __sys_accept(sock, (struct sockaddr *)&sin, &slen)) < 0)
&& (errno == EWOULDBLOCK || errno == EAGAIN)) {
printf("accept returned %d, errno %d\n", ret, errno);
fds.events = POLLRDNORM | POLLERR | POLLHUP;
fds.fd = sock;
__sys_poll(&fds, 1, 2000);
}
if (ret < 0)
err(1, "main: accept");
printf("main: got connection?\n");
return (0);
}
#if SIGNAL_TEST
static void
signal_handler(int sig)
#else
static void *
thread_entry(void *arg)
#endif
{
#if SIGNAL_TEST
printf("%s: rec'd signal %d...\n", __FUNCTION__, sig);
#else
printf("%s: sleeping 2 seconds...\n", __FUNCTION__);
sleep(2);
#endif
srandom(getpid() ^ time(NULL));
if ((random() & 0x00400000) != 0) {
printf("%s: shutdown()'ing socket...\n", __FUNCTION__);
if (shutdown(sock, SHUT_RDWR) == -1)
err(1, "thread: shutdown");
} else {
printf("%s: close()'ing socket...\n", __FUNCTION__);
if (close(sock) == -1)
err(1, "thread: shutdown");
}
#if !SIGNAL_TEST
return (NULL);
#endif
}
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?200208281720.g7SHK4xA015629>
