summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2006-10-03 02:59:37 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2006-10-03 02:59:37 +0000
commit985672e305143e6bee0ba4c190b0771bd2f8746e (patch)
tree7871ff1c7df149af49e577edfd6cd33900013b09
parent07706ccde7070f5695b2b92d66775c561609d513 (diff)
Last Part of file descriptor race and deadlock corrections.
When a fd enters the closing state prevent any threads from polling the fd and reschedule the thread with the closing_fd flag set. This fixes a class of deadlocks where a thread is blocked waiting for data (that may never arrive) and a later thread calls close() or dup2() on the fd. okay brad@
-rw-r--r--lib/libpthread/uthread/pthread_private.h8
-rw-r--r--lib/libpthread/uthread/uthread_accept.c8
-rw-r--r--lib/libpthread/uthread/uthread_connect.c38
-rw-r--r--lib/libpthread/uthread/uthread_kern.c72
-rw-r--r--lib/libpthread/uthread/uthread_kevent.c7
-rw-r--r--lib/libpthread/uthread/uthread_poll.c6
-rw-r--r--lib/libpthread/uthread/uthread_read.c10
-rw-r--r--lib/libpthread/uthread/uthread_readv.c10
-rw-r--r--lib/libpthread/uthread/uthread_recvfrom.c8
-rw-r--r--lib/libpthread/uthread/uthread_recvmsg.c8
-rw-r--r--lib/libpthread/uthread/uthread_select.c7
-rw-r--r--lib/libpthread/uthread/uthread_sendmsg.c7
-rw-r--r--lib/libpthread/uthread/uthread_sendto.c7
-rw-r--r--lib/libpthread/uthread/uthread_write.c10
-rw-r--r--lib/libpthread/uthread/uthread_writev.c10
15 files changed, 167 insertions, 49 deletions
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h
index 43e55c2b001..5011cd94d08 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.57 2006/09/26 14:18:28 kurt Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.58 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -743,6 +743,12 @@ struct pthread {
*/
int interrupted;
+ /*
+ * Set to TRUE if a blocking operation was
+ * interrupted by a closing file descriptor.
+ */
+ int closing_fd;
+
/* Signal number when in state PS_SIGWAIT: */
int signo;
diff --git a/lib/libpthread/uthread/uthread_accept.c b/lib/libpthread/uthread/uthread_accept.c
index caaa398dc8a..6fe193aa986 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.10 2006/09/26 14:18:28 kurt Exp $ */
+/* $OpenBSD: uthread_accept.c,v 1.11 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -67,6 +67,7 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
/* Schedule the next thread: */
_thread_kern_sched_state(PS_FDR_WAIT, __FILE__,
@@ -78,6 +79,11 @@ accept(int fd, struct sockaddr * name, socklen_t *namelen)
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ /* Return an error status: */
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
/*
diff --git a/lib/libpthread/uthread/uthread_connect.c b/lib/libpthread/uthread/uthread_connect.c
index 8987e1b56df..70dfd8ef430 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.6 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_connect.c,v 1.7 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -57,20 +57,38 @@ connect(int fd, const struct sockaddr * name, socklen_t namelen)
(errno == EALREADY) || (errno == EAGAIN))) {
curthread->data.fd.fd = fd;
+ /* Reset the interrupted operation flag: */
+ curthread->interrupted = 0;
+ curthread->closing_fd = 0;
+
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
_thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
- tmpnamelen = sizeof(tmpname);
- /* 0 now lets see if it really worked */
- if (((ret = _thread_sys_getpeername(fd, &tmpname, &tmpnamelen)) < 0) && (errno == ENOTCONN)) {
+ /*
+ * Check if the operation was
+ * interrupted by a signal or
+ * a closing fd.
+ */
+ if (curthread->interrupted) {
+ errno = EINTR;
+ ret = -1;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
+ } else {
+ tmpnamelen = sizeof(tmpname);
+ /* 0 now lets see if it really worked */
+ if (((ret = _thread_sys_getpeername(fd, &tmpname, &tmpnamelen)) < 0) &&
+ (errno == ENOTCONN)) {
- /*
- * Get the error, this function
- * should not fail
- */
- errnolen = sizeof(errno);
- _thread_sys_getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno, &errnolen);
+ /*
+ * Get the error, this function
+ * should not fail
+ */
+ errnolen = sizeof(errno);
+ _thread_sys_getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno, &errnolen);
+ }
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_kern.c b/lib/libpthread/uthread/uthread_kern.c
index 0210a4b3ecf..dd7fe641a9f 100644
--- a/lib/libpthread/uthread/uthread_kern.c
+++ b/lib/libpthread/uthread/uthread_kern.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kern.c,v 1.31 2005/10/30 02:45:09 krw Exp $ */
+/* $OpenBSD: uthread_kern.c,v 1.32 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -695,37 +695,69 @@ _thread_kern_poll(int wait_reqd)
/* File descriptor read wait: */
case PS_FDR_WAIT:
- /* Limit number of polled files to table size: */
- if (nfds < _thread_dtablesize) {
- _thread_pfd_table[nfds].events = POLLRDNORM;
- _thread_pfd_table[nfds].fd = pthread->data.fd.fd;
- nfds++;
+ /* if fd is closing then reschedule this thread */
+ if (_thread_fd_table[pthread->data.fd.fd]->state == FD_ENTRY_CLOSING) {
+ pthread->closing_fd = 1;
+ PTHREAD_WAITQ_CLEARACTIVE();
+ PTHREAD_WORKQ_REMOVE(pthread);
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ PTHREAD_WAITQ_SETACTIVE();
+ } else {
+ /* Limit number of polled files to table size: */
+ if (nfds < _thread_dtablesize) {
+ _thread_pfd_table[nfds].events = POLLRDNORM;
+ _thread_pfd_table[nfds].fd = pthread->data.fd.fd;
+ nfds++;
+ }
}
break;
/* File descriptor write wait: */
case PS_FDW_WAIT:
- /* Limit number of polled files to table size: */
- if (nfds < _thread_dtablesize) {
- _thread_pfd_table[nfds].events = POLLWRNORM;
- _thread_pfd_table[nfds].fd = pthread->data.fd.fd;
- nfds++;
+ /* if fd is closing then reschedule this thread */
+ if (_thread_fd_table[pthread->data.fd.fd]->state == FD_ENTRY_CLOSING) {
+ pthread->closing_fd = 1;
+ PTHREAD_WAITQ_CLEARACTIVE();
+ PTHREAD_WORKQ_REMOVE(pthread);
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ PTHREAD_WAITQ_SETACTIVE();
+ } else {
+ /* Limit number of polled files to table size: */
+ if (nfds < _thread_dtablesize) {
+ _thread_pfd_table[nfds].events = POLLWRNORM;
+ _thread_pfd_table[nfds].fd = pthread->data.fd.fd;
+ nfds++;
+ }
}
break;
/* File descriptor poll or select wait: */
case PS_POLL_WAIT:
case PS_SELECT_WAIT:
- /* Limit number of polled files to table size: */
- if (pthread->data.poll_data->nfds + nfds <
- _thread_dtablesize) {
- for (i = 0; i < pthread->data.poll_data->nfds; i++) {
- _thread_pfd_table[nfds + i].fd =
- pthread->data.poll_data->fds[i].fd;
- _thread_pfd_table[nfds + i].events =
- pthread->data.poll_data->fds[i].events;
+ /* if fd is closing then reschedule this thread */
+ for (i = 0; i < pthread->data.poll_data->nfds; i++) {
+ if (_thread_fd_table[pthread->data.poll_data->fds[i].fd]->state == FD_ENTRY_CLOSING) {
+ pthread->closing_fd = 1;
+ PTHREAD_WAITQ_CLEARACTIVE();
+ PTHREAD_WORKQ_REMOVE(pthread);
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ PTHREAD_WAITQ_SETACTIVE();
+ break;
+ }
+ }
+ /* if the thread was not rescheduled by a closing fd then add files */
+ if (pthread->closing_fd == 0) {
+ /* Limit number of polled files to table size: */
+ if (pthread->data.poll_data->nfds + nfds <
+ _thread_dtablesize) {
+ for (i = 0; i < pthread->data.poll_data->nfds; i++) {
+ _thread_pfd_table[nfds + i].fd =
+ pthread->data.poll_data->fds[i].fd;
+ _thread_pfd_table[nfds + i].events =
+ pthread->data.poll_data->fds[i].events;
+ }
+ nfds += pthread->data.poll_data->nfds;
}
- nfds += pthread->data.poll_data->nfds;
}
break;
diff --git a/lib/libpthread/uthread/uthread_kevent.c b/lib/libpthread/uthread/uthread_kevent.c
index f687e70f7f1..e810900418a 100644
--- a/lib/libpthread/uthread/uthread_kevent.c
+++ b/lib/libpthread/uthread/uthread_kevent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kevent.c,v 1.4 2003/10/19 05:27:03 brad Exp $ */
+/* $OpenBSD: uthread_kevent.c,v 1.5 2006/10/03 02:59:36 kurt Exp $ */
/*-
* Copyright (c) 2000 Jonathan Lemon <jlemon@flugsvamp.com>
@@ -60,6 +60,7 @@ kevent(int kq, const struct kevent *changelist, int nchanges,
do {
/* Reset the interrupted and timeout flags: */
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
curthread->timeout = 0;
_thread_kern_sched_state(PS_FDR_WAIT,
@@ -69,6 +70,10 @@ kevent(int kq, const struct kevent *changelist, int nchanges,
errno = EINTR;
rc = -1;
break;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ rc = -1;
+ break;
}
rc = _thread_sys_kevent(kq, NULL, 0,
eventlist, nevents, &nullts);
diff --git a/lib/libpthread/uthread/uthread_poll.c b/lib/libpthread/uthread/uthread_poll.c
index dc276fa350a..48d25f38d9b 100644
--- a/lib/libpthread/uthread/uthread_poll.c
+++ b/lib/libpthread/uthread/uthread_poll.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_poll.c,v 1.11 2004/11/30 00:14:51 pat Exp $ */
+/* $OpenBSD: uthread_poll.c,v 1.12 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1999 Daniel Eischen <eischen@vigrid.com>
* All rights reserved.
@@ -91,10 +91,14 @@ poll(struct pollfd fds[], nfds_t nfds, int timeout)
curthread->data.poll_data = &data;
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_POLL_WAIT, __FILE__, __LINE__);
if (curthread->interrupted) {
errno = EINTR;
ret = -1;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
} else {
ret = data.nfds;
}
diff --git a/lib/libpthread/uthread/uthread_read.c b/lib/libpthread/uthread/uthread_read.c
index 8455c97d2f5..9c3ef425c52 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.8 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_read.c,v 1.9 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -77,18 +77,24 @@ read(int fd, void *buf, size_t nbytes)
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDR_WAIT,
__FILE__, __LINE__);
/*
* Check if the operation was
- * interrupted by a signal
+ * interrupted by a signal or
+ * a closing fd.
*/
if (curthread->interrupted) {
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
break;
diff --git a/lib/libpthread/uthread/uthread_readv.c b/lib/libpthread/uthread/uthread_readv.c
index a83002fb5c0..7019df3af52 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.8 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_readv.c,v 1.9 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -75,18 +75,24 @@ readv(int fd, const struct iovec * iov, int iovcnt)
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDR_WAIT,
__FILE__, __LINE__);
/*
* Check if the operation was
- * interrupted by a signal
+ * interrupted by a signal or
+ * a closing fd.
*/
if (curthread->interrupted) {
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
break;
diff --git a/lib/libpthread/uthread/uthread_recvfrom.c b/lib/libpthread/uthread/uthread_recvfrom.c
index 0c693de57a1..21ff7e3f6a5 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.7 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_recvfrom.c,v 1.8 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -58,6 +58,7 @@ recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, sockl
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
/* Check if the wait was interrupted: */
@@ -66,6 +67,11 @@ recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, sockl
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ /* Return an error status: */
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_recvmsg.c b/lib/libpthread/uthread/uthread_recvmsg.c
index 5e8f13bd6dc..fa455395938 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.6 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_recvmsg.c,v 1.7 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -58,6 +58,7 @@ recvmsg(int fd, struct msghdr *msg, int flags)
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
/* Check if the wait was interrupted: */
@@ -66,6 +67,11 @@ recvmsg(int fd, struct msghdr *msg, int flags)
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ /* Return an error status: */
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_select.c b/lib/libpthread/uthread/uthread_select.c
index acc5d3017ae..f360ef2b425 100644
--- a/lib/libpthread/uthread/uthread_select.c
+++ b/lib/libpthread/uthread/uthread_select.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_select.c,v 1.11 2004/01/03 07:35:10 brad Exp $ */
+/* $OpenBSD: uthread_select.c,v 1.12 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -165,11 +165,16 @@ select(int numfds, fd_set * readfds, fd_set * writefds,
(f_wait != 0)) {
curthread->data.poll_data = &data;
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
if (curthread->interrupted) {
errno = EINTR;
data.nfds = 0;
ret = -1;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ data.nfds = 0;
+ ret = -1;
} else
ret = data.nfds;
}
diff --git a/lib/libpthread/uthread/uthread_sendmsg.c b/lib/libpthread/uthread/uthread_sendmsg.c
index 7cfb714606a..2995af1e024 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.6 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_sendmsg.c,v 1.7 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -58,6 +58,7 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
/* Check if the operation was interrupted: */
@@ -65,6 +66,10 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_sendto.c b/lib/libpthread/uthread/uthread_sendto.c
index 5b342315da3..09b1644d659 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.7 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_sendto.c,v 1.8 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -58,6 +58,7 @@ sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * t
/* Set the timeout: */
_thread_kern_set_timeout(NULL);
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
/* Check if the operation was interrupted: */
@@ -65,6 +66,10 @@ sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * t
errno = EINTR;
ret = -1;
break;
+ } else if (curthread->closing_fd) {
+ errno = EBADF;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_write.c b/lib/libpthread/uthread/uthread_write.c
index 71581d05387..2c4ed1076ff 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.11 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_write.c,v 1.12 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -105,6 +105,7 @@ write(int fd, const void *buf, size_t nbytes)
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDW_WAIT,
__FILE__, __LINE__);
@@ -113,13 +114,16 @@ write(int fd, const void *buf, size_t nbytes)
* Check if the operation was
* interrupted by a signal
*/
- if (curthread->interrupted) {
+ if (curthread->interrupted || curthread->closing_fd) {
if (num > 0) {
/* Return partial success: */
ret = num;
} else {
/* Return an error: */
- errno = EINTR;
+ if (curthread->closing_fd)
+ errno = EBADF;
+ else
+ errno = EINTR;
ret = -1;
}
}
diff --git a/lib/libpthread/uthread/uthread_writev.c b/lib/libpthread/uthread/uthread_writev.c
index cf7733f6290..45b1c80a2ee 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.11 2006/09/22 19:04:33 kurt Exp $ */
+/* $OpenBSD: uthread_writev.c,v 1.12 2006/10/03 02:59:36 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -174,6 +174,7 @@ writev(int fd, const struct iovec * iov, int iovcnt)
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
+ curthread->closing_fd = 0;
_thread_kern_sched_state(PS_FDW_WAIT,
__FILE__, __LINE__);
@@ -182,13 +183,16 @@ writev(int fd, const struct iovec * iov, int iovcnt)
* Check if the operation was
* interrupted by a signal
*/
- if (curthread->interrupted) {
+ if (curthread->interrupted || curthread->closing_fd) {
if (num > 0) {
/* Return partial success: */
ret = num;
} else {
/* Return an error: */
- errno = EINTR;
+ if (curthread->closing_fd)
+ errno = EBADF;
+ else
+ errno = EINTR;
ret = -1;
}
}