diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2006-10-03 02:59:37 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2006-10-03 02:59:37 +0000 |
commit | 985672e305143e6bee0ba4c190b0771bd2f8746e (patch) | |
tree | 7871ff1c7df149af49e577edfd6cd33900013b09 | |
parent | 07706ccde7070f5695b2b92d66775c561609d513 (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.h | 8 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_accept.c | 8 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_connect.c | 38 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_kern.c | 72 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_kevent.c | 7 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_poll.c | 6 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_read.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_readv.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_recvfrom.c | 8 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_recvmsg.c | 8 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_select.c | 7 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sendmsg.c | 7 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sendto.c | 7 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_write.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_writev.c | 10 |
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; } } |