summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2006-09-22 19:04:34 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2006-09-22 19:04:34 +0000
commit7b0347847c0d6eea5eea4d695761d24f1b151d53 (patch)
tree1f3f8ccccc135dfe4bbb20426cc5557f14403d53 /lib
parentd18267fdcf69320a8929dd06de2610e29bbb2b75 (diff)
Part 1 of file descriptor race and deadlock corrections.
File status flags should be shared for dup'ed file descriptors. However fd_table_entry's should not be shared for dup'ed file descriptors so they can be independently be closed without interfering with dup'ed fd's. - split out file status flags into its own structure fs_flags to manage sharing of status flags between dup'ed file descriptors. - when duplicating a fd, initialize a new fd_table_entry for the new fd, but share the status flags via status_flags. - consolidate the code that sets the underlying system fd to be non-blocking to a new function _thread_fs_flags_init() - consolidate the code that sets the underlying system fd back to blocking into a new function _thread_fs_flags_replace() This change is needed as a prerequisite to the coming race and deadlock corrections. okay marc@
Diffstat (limited to 'lib')
-rw-r--r--lib/libpthread/uthread/pthread_private.h17
-rw-r--r--lib/libpthread/uthread/uthread_accept.c10
-rw-r--r--lib/libpthread/uthread/uthread_close.c40
-rw-r--r--lib/libpthread/uthread/uthread_closefrom.c30
-rw-r--r--lib/libpthread/uthread/uthread_connect.c4
-rw-r--r--lib/libpthread/uthread/uthread_dup.c10
-rw-r--r--lib/libpthread/uthread/uthread_dup2.c40
-rw-r--r--lib/libpthread/uthread/uthread_execve.c4
-rw-r--r--lib/libpthread/uthread/uthread_exit.c4
-rw-r--r--lib/libpthread/uthread/uthread_fcntl.c11
-rw-r--r--lib/libpthread/uthread/uthread_fd.c271
-rw-r--r--lib/libpthread/uthread/uthread_fork.c4
-rw-r--r--lib/libpthread/uthread/uthread_ioctl.c6
-rw-r--r--lib/libpthread/uthread/uthread_kqueue.c4
-rw-r--r--lib/libpthread/uthread/uthread_open.c4
-rw-r--r--lib/libpthread/uthread/uthread_pipe.c6
-rw-r--r--lib/libpthread/uthread/uthread_read.c6
-rw-r--r--lib/libpthread/uthread/uthread_readv.c6
-rw-r--r--lib/libpthread/uthread/uthread_recvfrom.c5
-rw-r--r--lib/libpthread/uthread/uthread_recvmsg.c5
-rw-r--r--lib/libpthread/uthread/uthread_sendmsg.c5
-rw-r--r--lib/libpthread/uthread/uthread_sendto.c5
-rw-r--r--lib/libpthread/uthread/uthread_sig.c4
-rw-r--r--lib/libpthread/uthread/uthread_socket.c4
-rw-r--r--lib/libpthread/uthread/uthread_socketpair.c6
-rw-r--r--lib/libpthread/uthread/uthread_write.c6
-rw-r--r--lib/libpthread/uthread/uthread_writev.c6
27 files changed, 305 insertions, 218 deletions
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h
index 83d87db2292..35c927e31fa 100644
--- a/lib/libpthread/uthread/pthread_private.h
+++ b/lib/libpthread/uthread/pthread_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pthread_private.h,v 1.55 2006/01/06 18:53:04 millert Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.56 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -497,6 +497,15 @@ enum pthread_state {
*/
/*
+ * File status flags struture - shared for dup'ed fd's
+ */
+struct fs_flags {
+ spinlock_t lock;
+ int flags;
+ int refcnt;
+};
+
+/*
* File descriptor table structure.
*/
struct fd_table_entry {
@@ -517,8 +526,7 @@ struct fd_table_entry {
int w_lineno; /* Write lock src line no. */
int r_lockcount; /* Count for FILE read locks. */
int w_lockcount; /* Count for FILE write locks.*/
- int flags; /* Flags used in open. */
- int refcnt; /* how many fds use this entry*/
+ struct fs_flags *status_flags; /* Shared file status flags. */
};
struct pthread_poll_data {
@@ -1122,8 +1130,9 @@ void _thread_sig_init(void);
void _thread_start(void);
void _thread_start_sig_handler(void);
void _thread_seterrno(pthread_t,int);
+void _thread_fs_flags_replace(int, struct fs_flags *);
void _thread_fd_init(void);
-int _thread_fd_table_init(int);
+int _thread_fd_table_init(int, struct fs_flags *);
int _thread_fd_table_dup(int, int);
void _thread_fd_table_remove(int);
void _thread_fd_unlock_owned(pthread_t);
diff --git a/lib/libpthread/uthread/uthread_accept.c b/lib/libpthread/uthread/uthread_accept.c
index eb88a166753..a84312ba56f 100644
--- a/lib/libpthread/uthread/uthread_accept.c
+++ b/lib/libpthread/uthread/uthread_accept.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_accept.c,v 1.8 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_accept.c,v 1.9 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -55,7 +55,7 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
/* Enter a loop to wait for a connection request: */
while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
/* Check if the socket is to block: */
- if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ if ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
/* Save the socket file descriptor: */
curthread->data.fd.fd = fd;
@@ -93,12 +93,12 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
* as _thread_fd_table_init *may* have turned the flag on.
*/
if (ret != -1) {
- if (_thread_fd_table_init(ret) != 0) {
+ if (_thread_fd_table_init(ret, NULL) != 0) {
/* Quietly close the socket: */
_thread_sys_close(ret);
ret = -1;
- } else if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)
- _thread_fd_table[ret]->flags &= ~O_NONBLOCK;
+ } else if ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0)
+ _thread_fd_table[ret]->status_flags->flags &= ~O_NONBLOCK;
}
/* Unlock the file descriptor: */
diff --git a/lib/libpthread/uthread/uthread_close.c b/lib/libpthread/uthread/uthread_close.c
index c850d50a464..fa45be87e68 100644
--- a/lib/libpthread/uthread/uthread_close.c
+++ b/lib/libpthread/uthread/uthread_close.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_close.c,v 1.11 2003/12/23 20:03:54 marc Exp $ */
+/* $OpenBSD: uthread_close.c,v 1.12 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -35,8 +35,6 @@
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
@@ -44,9 +42,7 @@
int
close(int fd)
{
- int flags;
int ret;
- struct stat sb;
/* This is a cancelation point: */
_thread_enter_cancellation_point();
@@ -59,40 +55,6 @@ close(int fd)
/* unknown to thread kernel, let system handle the close */
ret = _thread_sys_close(fd);
else if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) {
- /*
- * Check if the file should be left as blocking.
- *
- * This is so that the file descriptors shared with a parent
- * process aren't left set to non-blocking if the child
- * closes them prior to exit. An example where this causes
- * problems with /bin/sh is when a child closes stdin.
- *
- * Setting a file as blocking causes problems if a threaded
- * parent accesses the file descriptor before the child exits.
- * Once the threaded parent receives a SIGCHLD then it resets
- * all of its files to non-blocking, and so it is then safe
- * to access them.
- *
- * Pipes are not set to blocking when they are closed, as
- * the parent and child will normally close the file
- * descriptor of the end of the pipe that they are not
- * using, which would then cause any reads to block
- * indefinitely.
- *
- * Files that we cannot fstat are probably not regular
- * so we don't bother with them.
- */
-
- if ((_thread_sys_fstat(fd, &sb) == 0) &&
- ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) &&
- (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0))
- {
- /* Get the current flags: */
- flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
- /* Clear the nonblocking file descriptor flag: */
- _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
- }
-
/* XXX: Assumes well behaved threads. */
/* XXX: Defer real close to avoid race condition */
_thread_fd_table_remove(fd);
diff --git a/lib/libpthread/uthread/uthread_closefrom.c b/lib/libpthread/uthread/uthread_closefrom.c
index 20d332f92a7..d80c0cff21d 100644
--- a/lib/libpthread/uthread/uthread_closefrom.c
+++ b/lib/libpthread/uthread/uthread_closefrom.c
@@ -1,39 +1,15 @@
-/* $OpenBSD: uthread_closefrom.c,v 1.1 2004/01/15 22:22:11 marc Exp $ */
+/* $OpenBSD: uthread_closefrom.c,v 1.2 2006/09/22 19:04:33 kurt Exp $ */
/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
#include <sys/stat.h>
#include <errno.h>
-#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include "pthread_private.h"
-/*
- * Reset the non-blocking flag if necessary. Remove the fd table entry
- * for the given fd.
- */
-static void
-_close_flags(int fd)
-{
- struct stat sb;
- int flags;
-
- if (_FD_LOCK(fd, FD_RDWR, NULL) == 0) {
- if ((_thread_sys_fstat(fd, &sb) == 0) &&
- ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) &&
- (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0)) {
- /* Get the current flags: */
- flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
- /* Clear the nonblocking file descriptor flag: */
- _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
- }
- _thread_fd_table_remove(fd);
- }
-}
-
int
closefrom(int fd)
{
@@ -60,7 +36,7 @@ closefrom(int fd)
/* Reset flags and clean up the fd table for fds to close */
for (lock_fd = fd; lock_fd < _thread_dtablesize; lock_fd++)
if (_thread_fd_table[lock_fd] != NULL)
- _close_flags(lock_fd);
+ _thread_fd_table_remove(lock_fd);
/* Now let the system do its thing */
ret = _thread_sys_closefrom(fd);
@@ -68,6 +44,6 @@ closefrom(int fd)
_thread_leave_cancellation_point();
- return ret;
+ return (ret);
}
diff --git a/lib/libpthread/uthread/uthread_connect.c b/lib/libpthread/uthread/uthread_connect.c
index 85e344f2975..8987e1b56df 100644
--- a/lib/libpthread/uthread/uthread_connect.c
+++ b/lib/libpthread/uthread/uthread_connect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_connect.c,v 1.5 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_connect.c,v 1.6 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -52,7 +52,7 @@ connect(int fd, const struct sockaddr * name, socklen_t namelen)
if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) {
if ((ret = _thread_sys_connect(fd, name, namelen)) < 0) {
- if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) &&
+ if (!(_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) &&
((errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
(errno == EALREADY) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
diff --git a/lib/libpthread/uthread/uthread_dup.c b/lib/libpthread/uthread/uthread_dup.c
index 9ca6343043a..7b7d01c3069 100644
--- a/lib/libpthread/uthread/uthread_dup.c
+++ b/lib/libpthread/uthread/uthread_dup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_dup.c,v 1.5 2003/02/05 05:51:51 marc Exp $ */
+/* $OpenBSD: uthread_dup.c,v 1.6 2006/09/22 19:04:33 kurt Exp $ */
/* PUBLIC DOMAIN <marc@snafu.org> */
#include <unistd.h>
@@ -14,11 +14,13 @@ dup(int fd)
ret = _FD_LOCK(fd, FD_RDWR, NULL);
if (ret == 0) {
ret = _thread_sys_dup(fd);
- if (ret != -1)
- if (_thread_fd_table_dup(fd, ret) == -1) {
- close(ret);
+ if (ret != -1) {
+ if (_thread_fd_table_init(ret,
+ _thread_fd_table[fd]->status_flags) == -1) {
+ _thread_sys_close(ret);
ret = -1;
}
+ }
_FD_UNLOCK(fd, FD_RDWR);
}
return (ret);
diff --git a/lib/libpthread/uthread/uthread_dup2.c b/lib/libpthread/uthread/uthread_dup2.c
index e0a1dc5d972..d8ef28d729d 100644
--- a/lib/libpthread/uthread/uthread_dup2.c
+++ b/lib/libpthread/uthread/uthread_dup2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_dup2.c,v 1.7 2003/02/05 05:51:51 marc Exp $ */
+/* $OpenBSD: uthread_dup2.c,v 1.8 2006/09/22 19:04:33 kurt Exp $ */
/* PUBLIC DOMAIN <marc@snafu.org> */
#include <errno.h>
@@ -11,17 +11,45 @@ int
dup2(int fd, int newfd)
{
int ret;
+ int saved_errno;
+ int newfd_opened;
if (newfd >= 0 && newfd < _thread_dtablesize &&
newfd != _thread_kern_pipe[0] && newfd != _thread_kern_pipe[1]) {
ret = _FD_LOCK(fd, FD_RDWR, NULL);
if (ret == 0) {
- ret = _thread_sys_dup2(fd, newfd);
- if (ret != -1)
- if (_thread_fd_table_dup(fd, newfd) == -1) {
- close(newfd);
- ret = -1;
+ newfd_opened = _thread_fd_table[newfd] != NULL;
+ if (!newfd_opened ||
+ (ret = _FD_LOCK(newfd, FD_RDWR, NULL)) == 0) {
+ /*
+ * If newfd was open then drop reference
+ * and reset flags if needed.
+ */
+ if (newfd_opened)
+ _thread_fs_flags_replace(newfd, NULL);
+ ret = _thread_sys_dup2(fd, newfd);
+ if (ret != -1)
+ ret = _thread_fd_table_init(newfd,
+ _thread_fd_table[fd]->status_flags);
+ /*
+ * If the dup2 or the _thread_fd_table_init
+ * failed we've already removed the status
+ * flags, so finish closing newfd. Return
+ * the current errno in case the sys_close
+ * fails too.
+ */
+ if (ret == -1) {
+ saved_errno = errno;
+
+ if (newfd_opened)
+ _thread_fd_table_remove(newfd);
+ _thread_sys_close(newfd);
+
+ errno = saved_errno ;
+ } else if (newfd_opened) {
+ _FD_UNLOCK(newfd, FD_RDWR);
}
+ }
_FD_UNLOCK(fd, FD_RDWR);
}
} else {
diff --git a/lib/libpthread/uthread/uthread_execve.c b/lib/libpthread/uthread/uthread_execve.c
index e5df58d97f3..7769d3e6685 100644
--- a/lib/libpthread/uthread/uthread_execve.c
+++ b/lib/libpthread/uthread/uthread_execve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_execve.c,v 1.7 2003/10/22 00:24:14 brad Exp $ */
+/* $OpenBSD: uthread_execve.c,v 1.8 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -68,7 +68,7 @@ execve(const char *name, char *const * argv, char *const * envp)
for (i = 0; i < _thread_dtablesize; i++) {
/* Check if this file descriptor is in use: */
if (_thread_fd_table[i] != NULL &&
- !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ !(_thread_fd_table[i]->status_flags->flags & O_NONBLOCK)) {
/* Skip if the close-on-exec flag is set */
flags = _thread_sys_fcntl(i, F_GETFD, NULL);
if ((flags & FD_CLOEXEC) != 0)
diff --git a/lib/libpthread/uthread/uthread_exit.c b/lib/libpthread/uthread/uthread_exit.c
index 91f41343583..94fc1699c37 100644
--- a/lib/libpthread/uthread/uthread_exit.c
+++ b/lib/libpthread/uthread/uthread_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_exit.c,v 1.17 2002/11/07 02:56:20 marc Exp $ */
+/* $OpenBSD: uthread_exit.c,v 1.18 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -67,7 +67,7 @@ _exit(int status)
for (i = 0; i < _thread_dtablesize; i++) {
/* Check if this file descriptor is in use: */
if (_thread_fd_table[i] != NULL &&
- !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ !(_thread_fd_table[i]->status_flags->flags & O_NONBLOCK)) {
/* Get the current flags: */
flags = _thread_sys_fcntl(i, F_GETFL, NULL);
/* Clear the nonblocking file descriptor flag: */
diff --git a/lib/libpthread/uthread/uthread_fcntl.c b/lib/libpthread/uthread/uthread_fcntl.c
index 8955618efcd..0b772778ece 100644
--- a/lib/libpthread/uthread/uthread_fcntl.c
+++ b/lib/libpthread/uthread/uthread_fcntl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_fcntl.c,v 1.7 2003/02/04 22:14:27 marc Exp $ */
+/* $OpenBSD: uthread_fcntl.c,v 1.8 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -70,7 +70,8 @@ fcntl(int fd, int cmd,...)
if ((ret = _thread_sys_fcntl(fd, cmd, oldfd)) < 0) {
}
/* Initialise the file descriptor table entry: */
- else if (_thread_fd_table_dup(fd, ret) != 0) {
+ else if (_thread_fd_table_init(ret,
+ _thread_fd_table[fd]->status_flags) == -1) {
/* Quietly close the file: */
_thread_sys_close(ret);
@@ -86,7 +87,7 @@ fcntl(int fd, int cmd,...)
ret = _thread_sys_fcntl(fd, cmd, 0);
break;
case F_GETFL:
- ret = _thread_fd_table[fd]->flags;
+ ret = _thread_fd_table[fd]->status_flags->flags;
break;
case F_SETFL:
/*
@@ -116,10 +117,10 @@ fcntl(int fd, int cmd,...)
*/
} else if (nonblock)
/* A non-blocking descriptor: */
- _thread_fd_table[fd]->flags = flags | O_NONBLOCK;
+ _thread_fd_table[fd]->status_flags->flags = flags | O_NONBLOCK;
else
/* Save the flags: */
- _thread_fd_table[fd]->flags = flags & ~O_NONBLOCK;
+ _thread_fd_table[fd]->status_flags->flags = flags & ~O_NONBLOCK;
break;
default:
/* Might want to make va_arg use a union */
diff --git a/lib/libpthread/uthread/uthread_fd.c b/lib/libpthread/uthread/uthread_fd.c
index a32a09c07e9..9cfae2af508 100644
--- a/lib/libpthread/uthread/uthread_fd.c
+++ b/lib/libpthread/uthread/uthread_fd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_fd.c,v 1.22 2004/06/07 21:11:23 marc Exp $ */
+/* $OpenBSD: uthread_fd.c,v 1.23 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
@@ -47,6 +48,124 @@ static spinlock_t fd_table_lock = _SPINLOCK_INITIALIZER;
/*
* Build a new fd entry and return it.
*/
+static struct fs_flags *
+_thread_fs_flags_entry(void)
+{
+ struct fs_flags *entry;
+
+ entry = (struct fs_flags *) malloc(sizeof(struct fs_flags));
+ if (entry != NULL) {
+ memset(entry, 0, sizeof *entry);
+ _SPINLOCK_INIT(&entry->lock);
+ }
+ return entry;
+}
+
+/*
+ * Initialize a new status_flags entry and set system
+ * file descriptor non-blocking.
+ */
+static int
+_thread_fs_flags_init(struct fs_flags *status_flags, int fd)
+{
+ int ret = 0;
+ int saved_errno;
+
+ status_flags->flags = _thread_sys_fcntl(fd, F_GETFL, 0);
+ if (status_flags->flags == -1)
+ /* use the errno fcntl returned */
+ ret = -1;
+ else {
+ /*
+ * Make the file descriptor non-blocking.
+ * This might fail if the device driver does
+ * not support non-blocking calls, or if the
+ * driver is naturally non-blocking.
+ */
+ if ((status_flags->flags & O_NONBLOCK) == 0) {
+ saved_errno = errno;
+ _thread_sys_fcntl(fd, F_SETFL,
+ status_flags->flags | O_NONBLOCK);
+ errno = saved_errno;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * If existing entry's status_flags don't match new one,
+ * then replace the current status flags with the new one.
+ * It is assumed the entry is locked with a FD_RDWR
+ * lock when this function is called.
+ */
+void
+_thread_fs_flags_replace(int fd, struct fs_flags *new_status_flags)
+{
+ struct fd_table_entry *entry = _thread_fd_table[fd];
+ struct fs_flags *old_status_flags;
+ struct stat sb;
+ int flags;
+
+ if (entry->status_flags != new_status_flags) {
+ if (entry->status_flags != NULL) {
+ old_status_flags = entry->status_flags;
+ _SPINLOCK(&old_status_flags->lock);
+ old_status_flags->refcnt -= 1;
+ if (old_status_flags->refcnt <= 0) {
+ /*
+ * Check if the file should be left as blocking.
+ *
+ * This is so that the file descriptors shared with a parent
+ * process aren't left set to non-blocking if the child
+ * closes them prior to exit. An example where this causes
+ * problems with /bin/sh is when a child closes stdin.
+ *
+ * Setting a file as blocking causes problems if a threaded
+ * parent accesses the file descriptor before the child exits.
+ * Once the threaded parent receives a SIGCHLD then it resets
+ * all of its files to non-blocking, and so it is then safe
+ * to access them.
+ *
+ * Pipes are not set to blocking when they are closed, as
+ * the parent and child will normally close the file
+ * descriptor of the end of the pipe that they are not
+ * using, which would then cause any reads to block
+ * indefinitely.
+ *
+ * Files that we cannot fstat are probably not regular
+ * so we don't bother with them.
+ *
+ * Also don't reset fd to blocking if we are replacing
+ * the status flags with a shared version.
+ */
+ if (new_status_flags != NULL &&
+ (_thread_sys_fstat(fd, &sb) == 0) &&
+ ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) &&
+ (old_status_flags->flags & O_NONBLOCK) == 0))
+ {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ free(old_status_flags);
+ } else
+ _SPINUNLOCK(&old_status_flags->lock);
+ }
+ /* replace with new status flags */
+ if (new_status_flags != NULL) {
+ _SPINLOCK(&new_status_flags->lock);
+ new_status_flags->refcnt += 1;
+ _SPINUNLOCK(&new_status_flags->lock);
+ }
+ entry->status_flags = new_status_flags;
+ }
+}
+
+/*
+ * Build a new fd entry and return it.
+ */
static struct fd_table_entry *
_thread_fd_entry(void)
{
@@ -75,14 +194,14 @@ _thread_fd_init(void)
int fd2;
int flag;
int *flags;
- struct fd_table_entry *entry;
+ struct fd_table_entry *entry1, *entry2;
+ struct fs_flags *status_flags;
saved_errno = errno;
flags = calloc(_thread_dtablesize, sizeof *flags);
if (flags == NULL)
PANIC("Cannot allocate memory for flags table");
-
/* read the current file flags */
for (fd = 0; fd < _thread_dtablesize; fd += 1)
flags[fd] = _thread_sys_fcntl(fd, F_GETFL, 0);
@@ -100,27 +219,38 @@ _thread_fd_init(void)
for (fd = 0; fd < _thread_dtablesize; fd += 1) {
if (flags[fd] == -1)
continue;
- entry = _thread_fd_entry();
- if (entry != NULL) {
- entry->flags = flags[fd];
+ entry1 = _thread_fd_entry();
+ status_flags = _thread_fs_flags_entry();
+ if (entry1 != NULL && status_flags != NULL) {
_thread_sys_fcntl(fd, F_SETFL,
- entry->flags ^ O_SYNC);
+ flags[fd] ^ O_SYNC);
for (fd2 = fd + 1; fd2 < _thread_dtablesize; fd2 += 1) {
if (flags[fd2] == -1)
continue;
flag = _thread_sys_fcntl(fd2, F_GETFL, 0);
if (flag != flags[fd2]) {
- entry->refcnt += 1;
- _thread_fd_table[fd2] = entry;
+ entry2 = _thread_fd_entry();
+ if (entry2 != NULL) {
+ status_flags->refcnt += 1;
+ entry2->status_flags = status_flags;
+ _thread_fd_table[fd2] = entry2;
+ } else
+ PANIC("Cannot allocate memory for flags table");
flags[fd2] = -1;
}
}
- if (entry->refcnt) {
- entry->refcnt += 1;
- _thread_fd_table[fd] = entry;
+ if (status_flags->refcnt) {
+ status_flags->refcnt += 1;
+ status_flags->flags = flags[fd];
+ entry1->status_flags = status_flags;
+ _thread_fd_table[fd] = entry1;
flags[fd] |= O_NONBLOCK;
- } else
- free(entry);
+ } else {
+ free(entry1);
+ free(status_flags);
+ }
+ } else {
+ PANIC("Cannot allocate memory for flags table");
}
}
_SPINUNLOCK(&fd_table_lock);
@@ -146,11 +276,11 @@ _thread_fd_init(void)
* calls.
*/
int
-_thread_fd_table_init(int fd)
+_thread_fd_table_init(int fd, struct fs_flags *status_flags)
{
int ret = 0;
struct fd_table_entry *entry;
- int saved_errno;
+ struct fs_flags *new_status_flags = NULL;
if (fd < 0 || fd >= _thread_dtablesize) {
/*
@@ -158,32 +288,24 @@ _thread_fd_table_init(int fd)
* descriptor error:
*/
errno = EBADF;
- ret = -1;
- } else if (_thread_fd_table[fd] == NULL) {
+ return (-1);
+ }
+
+ if (_thread_fd_table[fd] == NULL) {
/* First time for this fd, build an entry */
entry = _thread_fd_entry();
if (entry == NULL) {
errno = ENOMEM;
ret = -1;
} else {
- entry->flags = _thread_sys_fcntl(fd, F_GETFL, 0);
- if (entry->flags == -1)
- /* use the errno fcntl returned */
- ret = -1;
- else {
- /*
- * Make the file descriptor non-blocking.
- * This might fail if the device driver does
- * not support non-blocking calls, or if the
- * driver is naturally non-blocking.
- */
- if ((entry->flags & O_NONBLOCK) == 0) {
- saved_errno = errno;
- _thread_sys_fcntl(fd, F_SETFL,
- entry->flags | O_NONBLOCK);
- errno = saved_errno;
- }
-
+ if (status_flags == NULL) {
+ new_status_flags = _thread_fs_flags_entry();
+ if (new_status_flags == NULL)
+ ret = -1;
+ else
+ ret = _thread_fs_flags_init(new_status_flags, fd);
+ }
+ if (ret == 0) {
/* Lock the file descriptor table: */
_SPINLOCK(&fd_table_lock);
@@ -195,9 +317,19 @@ _thread_fd_table_init(int fd)
* it has the potential to recurse.
*/
if (_thread_fd_table[fd] == NULL) {
+ if (status_flags != NULL) {
+ _SPINLOCK(&status_flags->lock);
+ status_flags->refcnt += 1;
+ _SPINUNLOCK(&status_flags->lock);
+ entry->status_flags = status_flags;
+ } else {
+ new_status_flags->refcnt = 1;
+ entry->status_flags = new_status_flags;
+ }
/* This thread wins: */
- entry->refcnt += 1;
_thread_fd_table[fd] = entry;
+ entry = NULL;
+ new_status_flags = NULL;
}
/* Unlock the file descriptor table: */
@@ -207,11 +339,18 @@ _thread_fd_table_init(int fd)
/*
* If there was an error in getting the flags for
* the file or if another thread initialized the
- * table entry throw this entry away.
+ * table entry throw this entry and new_status_flags
+ * away.
*/
- if (entry->refcnt == 0)
+ if (entry != NULL)
free(entry);
+
+ if (new_status_flags != NULL)
+ free(new_status_flags);
}
+ } else {
+ if (status_flags != NULL)
+ _thread_fs_flags_replace(fd, status_flags);
}
/* Return the completion status: */
@@ -219,55 +358,18 @@ _thread_fd_table_init(int fd)
}
/*
- * Dup from_fd -> to_fd. from_fd is assumed to be locked (which
- * guarantees that _thread_fd_table[from_fd] exists).
- */
-int
-_thread_fd_table_dup(int from_fd, int to_fd)
-{
- struct fd_table_entry *entry;
- int ret;
-
- if (from_fd != to_fd) {
- /* release any existing to_fd table entry */
- entry = _thread_fd_table[to_fd];
- if (entry != NULL) {
- ret = _FD_LOCK(to_fd, FD_RDWR, NULL);
- if (ret != -1)
- _thread_fd_table_remove(to_fd);
- } else
- ret = 0;
-
- /* to_fd is a copy of from_fd */
- if (ret != -1) {
- _SPINLOCK(&fd_table_lock);
- _thread_fd_table[to_fd] = _thread_fd_table[from_fd];
- _thread_fd_table[to_fd]->refcnt += 1;
- _SPINUNLOCK(&fd_table_lock);
- }
- } else
- ret = 0;
-
- return (ret);
-}
-
-/*
- * Remove an fd entry from the table and free it if it's reference count
- * goes to zero. The entry is assumed to be locked with a RDWR lock! It
- * will be unlocked if it is not freed.
+ * Remove an fd entry from the table and replace its status flags
+ * with NULL. The entry is assummed to be locked with a RDWR lock.
*/
void
_thread_fd_table_remove(int fd)
{
- struct fd_table_entry *entry;
-
_SPINLOCK(&fd_table_lock);
- entry = _thread_fd_table[fd];
- if (--entry->refcnt == 0)
- free(entry);
- else
- _FD_UNLOCK(fd, FD_RDWR);
+
+ _thread_fs_flags_replace(fd, NULL);
+ free(_thread_fd_table[fd]);
_thread_fd_table[fd] = NULL;
+
_SPINUNLOCK(&fd_table_lock);
}
@@ -284,7 +386,7 @@ _thread_fd_unlock_thread(struct pthread *thread, int fd, int lock_type)
* Check that the file descriptor table is initialised for this
* entry:
*/
- ret = _thread_fd_table_init(fd);
+ ret = _thread_fd_table_init(fd, NULL);
if (ret == 0) {
entry = _thread_fd_table[fd];
@@ -443,7 +545,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
* Check that the file descriptor table is initialised for this
* entry:
*/
- ret = _thread_fd_table_init(fd);
+ ret = _thread_fd_table_init(fd, NULL);
if (ret == 0) {
entry = _thread_fd_table[fd];
@@ -453,6 +555,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
* thread's accesses:
*/
_SPINLOCK(&entry->lock);
+
/* Handle read locks */
if (lock_type == FD_READ || lock_type == FD_RDWR) {
/*
diff --git a/lib/libpthread/uthread/uthread_fork.c b/lib/libpthread/uthread/uthread_fork.c
index 09a3279392a..3c51d6cf305 100644
--- a/lib/libpthread/uthread/uthread_fork.c
+++ b/lib/libpthread/uthread/uthread_fork.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_fork.c,v 1.12 2005/10/30 03:37:34 brad Exp $ */
+/* $OpenBSD: uthread_fork.c,v 1.13 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -185,6 +185,8 @@ fork(void)
_thread_fd_table[i]->w_lineno = 0;
_thread_fd_table[i]->r_lockcount = 0;
_thread_fd_table[i]->w_lockcount = 0;
+ if (_thread_fd_table[i]->status_flags != NULL)
+ _SPINLOCK_INIT(&_thread_fd_table[i]->status_flags->lock);
/* Initialise the read/write queues: */
TAILQ_INIT(&_thread_fd_table[i]->r_queue);
diff --git a/lib/libpthread/uthread/uthread_ioctl.c b/lib/libpthread/uthread/uthread_ioctl.c
index d7daa17196b..a8347dfb94e 100644
--- a/lib/libpthread/uthread/uthread_ioctl.c
+++ b/lib/libpthread/uthread/uthread_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_ioctl.c,v 1.3 1999/11/25 07:01:37 d Exp $ */
+/* $OpenBSD: uthread_ioctl.c,v 1.4 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -58,8 +58,8 @@ ioctl(int fd, unsigned long request,...)
* twiddling the flag based on the request
*/
op = va_arg(ap, int *);
- _thread_fd_table[fd]->flags &= ~O_NONBLOCK;
- _thread_fd_table[fd]->flags |= ((*op) ? O_NONBLOCK : 0);
+ _thread_fd_table[fd]->status_flags->flags &= ~O_NONBLOCK;
+ _thread_fd_table[fd]->status_flags->flags |= ((*op) ? O_NONBLOCK : 0);
ret = 0;
break;
default:
diff --git a/lib/libpthread/uthread/uthread_kqueue.c b/lib/libpthread/uthread/uthread_kqueue.c
index 7ba41db1f48..638d9fe445a 100644
--- a/lib/libpthread/uthread/uthread_kqueue.c
+++ b/lib/libpthread/uthread/uthread_kqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kqueue.c,v 1.1 2003/10/22 00:25:42 brad Exp $ */
+/* $OpenBSD: uthread_kqueue.c,v 1.2 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 2003 Mark Peek <mp@freebsd.org>
@@ -46,7 +46,7 @@ kqueue(void)
/* Error creating socket. */
/* Initialise the entry in the file descriptor table: */
- } else if (_thread_fd_table_init(fd) != 0) {
+ } else if (_thread_fd_table_init(fd, NULL) != 0) {
_thread_sys_close(fd);
fd = -1;
}
diff --git a/lib/libpthread/uthread/uthread_open.c b/lib/libpthread/uthread/uthread_open.c
index bf55d7d8bb9..aa2d3dd9b56 100644
--- a/lib/libpthread/uthread/uthread_open.c
+++ b/lib/libpthread/uthread/uthread_open.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_open.c,v 1.6 2000/01/06 07:20:10 d Exp $ */
+/* $OpenBSD: uthread_open.c,v 1.7 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -63,7 +63,7 @@ open(const char *path, int flags,...)
if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
}
/* Initialise the file descriptor table entry: */
- else if (_thread_fd_table_init(fd) != 0) {
+ else if (_thread_fd_table_init(fd, NULL) != 0) {
/* Quietly close the file: */
_thread_sys_close(fd);
diff --git a/lib/libpthread/uthread/uthread_pipe.c b/lib/libpthread/uthread/uthread_pipe.c
index 6288ab82cbc..ca798183769 100644
--- a/lib/libpthread/uthread/uthread_pipe.c
+++ b/lib/libpthread/uthread/uthread_pipe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_pipe.c,v 1.3 1999/11/25 07:01:41 d Exp $ */
+/* $OpenBSD: uthread_pipe.c,v 1.4 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -43,8 +43,8 @@ pipe(int fds[2])
{
int ret;
if ((ret = _thread_sys_pipe(fds)) >= 0) {
- if (_thread_fd_table_init(fds[0]) != 0 ||
- _thread_fd_table_init(fds[1]) != 0) {
+ if (_thread_fd_table_init(fds[0], NULL) != 0 ||
+ _thread_fd_table_init(fds[1], NULL) != 0) {
_thread_sys_close(fds[0]);
_thread_sys_close(fds[1]);
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_read.c b/lib/libpthread/uthread/uthread_read.c
index b491ea99116..8455c97d2f5 100644
--- a/lib/libpthread/uthread/uthread_read.c
+++ b/lib/libpthread/uthread/uthread_read.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_read.c,v 1.7 2001/08/21 19:24:53 fgsch Exp $ */
+/* $OpenBSD: uthread_read.c,v 1.8 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -59,7 +59,7 @@ read(int fd, void *buf, size_t nbytes)
/* Lock the file descriptor for read: */
else if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
/* Get the read/write mode type: */
- type = _thread_fd_table[fd]->flags & O_ACCMODE;
+ type = _thread_fd_table[fd]->status_flags->flags & O_ACCMODE;
/* Check if the file is not open for read: */
if (type != O_RDONLY && type != O_RDWR) {
@@ -70,7 +70,7 @@ read(int fd, void *buf, size_t nbytes)
/* Perform a non-blocking read syscall: */
else while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) {
- if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ if ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
curthread->data.fd.fd = fd;
_thread_kern_set_timeout(NULL);
diff --git a/lib/libpthread/uthread/uthread_readv.c b/lib/libpthread/uthread/uthread_readv.c
index f87fa652c38..a83002fb5c0 100644
--- a/lib/libpthread/uthread/uthread_readv.c
+++ b/lib/libpthread/uthread/uthread_readv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_readv.c,v 1.7 2004/11/30 00:14:51 pat Exp $ */
+/* $OpenBSD: uthread_readv.c,v 1.8 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -55,7 +55,7 @@ readv(int fd, const struct iovec * iov, int iovcnt)
/* Lock the file descriptor for read: */
if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
/* Get the read/write mode type: */
- type = _thread_fd_table[fd]->flags & O_ACCMODE;
+ type = _thread_fd_table[fd]->status_flags->flags & O_ACCMODE;
/* Check if the file is not open for read: */
if (type != O_RDONLY && type != O_RDWR) {
@@ -68,7 +68,7 @@ readv(int fd, const struct iovec * iov, int iovcnt)
/* Perform a non-blocking readv syscall: */
while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) {
- if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 &&
+ if ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
curthread->data.fd.fd = fd;
_thread_kern_set_timeout(NULL);
diff --git a/lib/libpthread/uthread/uthread_recvfrom.c b/lib/libpthread/uthread/uthread_recvfrom.c
index 5817832a43c..0c693de57a1 100644
--- a/lib/libpthread/uthread/uthread_recvfrom.c
+++ b/lib/libpthread/uthread/uthread_recvfrom.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_recvfrom.c,v 1.6 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_recvfrom.c,v 1.7 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -51,7 +51,8 @@ recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, sockl
if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
while ((ret = _thread_sys_recvfrom(fd, buf, len, flags, from, from_len)) < 0) {
- if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ if (!(_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
/* Set the timeout: */
diff --git a/lib/libpthread/uthread/uthread_recvmsg.c b/lib/libpthread/uthread/uthread_recvmsg.c
index 6c1f9668c5e..5e8f13bd6dc 100644
--- a/lib/libpthread/uthread/uthread_recvmsg.c
+++ b/lib/libpthread/uthread/uthread_recvmsg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_recvmsg.c,v 1.5 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_recvmsg.c,v 1.6 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -51,7 +51,8 @@ recvmsg(int fd, struct msghdr *msg, int flags)
if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
while ((ret = _thread_sys_recvmsg(fd, msg, flags)) < 0) {
- if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ if (!(_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
/* Set the timeout: */
diff --git a/lib/libpthread/uthread/uthread_sendmsg.c b/lib/libpthread/uthread/uthread_sendmsg.c
index 5910e7b04cc..7cfb714606a 100644
--- a/lib/libpthread/uthread/uthread_sendmsg.c
+++ b/lib/libpthread/uthread/uthread_sendmsg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sendmsg.c,v 1.5 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_sendmsg.c,v 1.6 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -51,7 +51,8 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) {
while ((ret = _thread_sys_sendmsg(fd, msg, flags)) < 0) {
- if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ if (!(_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
/* Set the timeout: */
diff --git a/lib/libpthread/uthread/uthread_sendto.c b/lib/libpthread/uthread/uthread_sendto.c
index c2ad04b0e2a..5b342315da3 100644
--- a/lib/libpthread/uthread/uthread_sendto.c
+++ b/lib/libpthread/uthread/uthread_sendto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sendto.c,v 1.6 2003/12/23 19:31:05 brad Exp $ */
+/* $OpenBSD: uthread_sendto.c,v 1.7 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -51,7 +51,8 @@ sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * t
if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) {
while ((ret = _thread_sys_sendto(fd, msg, len, flags, to, to_len)) < 0) {
- if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ if (!(_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
/* Set the timeout: */
diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c
index a7cf1eb9fc4..7f4d9dd082c 100644
--- a/lib/libpthread/uthread/uthread_sig.c
+++ b/lib/libpthread/uthread/uthread_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sig.c,v 1.20 2003/04/30 17:54:17 marc Exp $ */
+/* $OpenBSD: uthread_sig.c,v 1.21 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -187,7 +187,7 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
for (i = 0; i < _thread_dtablesize; i++)
if (_thread_fd_table[i] != NULL)
_thread_sys_fcntl(i, F_SETFL,
- _thread_fd_table[i]->flags |
+ _thread_fd_table[i]->status_flags->flags |
O_NONBLOCK);
}
diff --git a/lib/libpthread/uthread/uthread_socket.c b/lib/libpthread/uthread/uthread_socket.c
index b4a96b8185a..3cecc3b57da 100644
--- a/lib/libpthread/uthread/uthread_socket.c
+++ b/lib/libpthread/uthread/uthread_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_socket.c,v 1.3 1999/11/25 07:01:46 d Exp $ */
+/* $OpenBSD: uthread_socket.c,v 1.4 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -50,7 +50,7 @@ socket(int af, int type, int protocol)
/* Error creating socket. */
/* Initialise the entry in the file descriptor table: */
- } else if (_thread_fd_table_init(fd) != 0) {
+ } else if (_thread_fd_table_init(fd, NULL) != 0) {
_thread_sys_close(fd);
fd = -1;
}
diff --git a/lib/libpthread/uthread/uthread_socketpair.c b/lib/libpthread/uthread/uthread_socketpair.c
index 5ccdf6ee602..bd824bb867d 100644
--- a/lib/libpthread/uthread/uthread_socketpair.c
+++ b/lib/libpthread/uthread/uthread_socketpair.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_socketpair.c,v 1.4 2000/01/06 07:21:35 d Exp $ */
+/* $OpenBSD: uthread_socketpair.c,v 1.5 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -46,8 +46,8 @@ socketpair(int af, int type, int protocol, int pair[2])
{
int ret;
if (!((ret = _thread_sys_socketpair(af, type, protocol, pair)) < 0))
- if (_thread_fd_table_init(pair[0]) != 0 ||
- _thread_fd_table_init(pair[1]) != 0) {
+ if (_thread_fd_table_init(pair[0], NULL) != 0 ||
+ _thread_fd_table_init(pair[1], NULL) != 0) {
_thread_sys_close(pair[0]);
_thread_sys_close(pair[1]);
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_write.c b/lib/libpthread/uthread/uthread_write.c
index 393b9da65c7..71581d05387 100644
--- a/lib/libpthread/uthread/uthread_write.c
+++ b/lib/libpthread/uthread/uthread_write.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_write.c,v 1.10 2003/12/22 00:33:42 brad Exp $ */
+/* $OpenBSD: uthread_write.c,v 1.11 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -62,7 +62,7 @@ write(int fd, const void *buf, size_t nbytes)
/* Lock the file descriptor for write: */
else if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) {
/* Get the read/write mode type: */
- type = _thread_fd_table[fd]->flags & O_ACCMODE;
+ type = _thread_fd_table[fd]->status_flags->flags & O_ACCMODE;
/* Check if the file is not open for write: */
if (type != O_WRONLY && type != O_RDWR) {
@@ -73,7 +73,7 @@ write(int fd, const void *buf, size_t nbytes)
else {
/* Check if file operations are to block */
- blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0);
+ blocking = ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0);
/*
* Loop while no error occurs and until the expected number
diff --git a/lib/libpthread/uthread/uthread_writev.c b/lib/libpthread/uthread/uthread_writev.c
index 020868ab58f..cf7733f6290 100644
--- a/lib/libpthread/uthread/uthread_writev.c
+++ b/lib/libpthread/uthread/uthread_writev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_writev.c,v 1.10 2004/12/12 21:56:07 brad Exp $ */
+/* $OpenBSD: uthread_writev.c,v 1.11 2006/09/22 19:04:33 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -79,7 +79,7 @@ writev(int fd, const struct iovec * iov, int iovcnt)
/* Lock the file descriptor for write: */
if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) {
/* Get the read/write mode type: */
- type = _thread_fd_table[fd]->flags & O_ACCMODE;
+ type = _thread_fd_table[fd]->status_flags->flags & O_ACCMODE;
/* Check if the file is not open for write: */
if (type != O_WRONLY && type != O_RDWR) {
@@ -93,7 +93,7 @@ writev(int fd, const struct iovec * iov, int iovcnt)
}
/* Check if file operations are to block */
- blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0);
+ blocking = ((_thread_fd_table[fd]->status_flags->flags & O_NONBLOCK) == 0);
/*
* Loop while no error occurs and until the expected number