summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2010-01-03 23:05:36 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2010-01-03 23:05:36 +0000
commit8028f6a67fe786e34cdc97e0f80c7fe8ce12194b (patch)
treedfd309174b9fe946bc94a645173a2e5b6bd67b6b /lib
parent8977d0817d5af955632b410a7411fb89d1143f34 (diff)
Make SO_RCVTIMEO and SO_SNDTIMEO work with pthreads. Fixes at least some of
the issues seen with www/varnish. With input and help from guenther@ and kurt@. guenther@ ok
Diffstat (limited to 'lib')
-rw-r--r--lib/libpthread/uthread/pthread_private.h10
-rw-r--r--lib/libpthread/uthread/uthread_fcntl.c24
-rw-r--r--lib/libpthread/uthread/uthread_fd.c34
-rw-r--r--lib/libpthread/uthread/uthread_read.c13
-rw-r--r--lib/libpthread/uthread/uthread_readv.c13
-rw-r--r--lib/libpthread/uthread/uthread_recvfrom.c10
-rw-r--r--lib/libpthread/uthread/uthread_recvmsg.c10
-rw-r--r--lib/libpthread/uthread/uthread_sendmsg.c9
-rw-r--r--lib/libpthread/uthread/uthread_sendto.c9
-rw-r--r--lib/libpthread/uthread/uthread_sig.c4
-rw-r--r--lib/libpthread/uthread/uthread_sigmask.c4
-rw-r--r--lib/libpthread/uthread/uthread_write.c13
-rw-r--r--lib/libpthread/uthread/uthread_writev.c13
13 files changed, 128 insertions, 38 deletions
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h
index 324f6d20900..513ded4432d 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.73 2009/12/06 17:54:59 kurt Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.74 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -501,11 +501,16 @@ enum pthread_state {
#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
+/* Get a suitable argument for _thread_kern_set_timeout(), given an fd */
+#define _FD_RCVTIMEO(_fd) _thread_fd_timeout((_fd), 0)
+#define _FD_SNDTIMEO(_fd) _thread_fd_timeout((_fd), 1)
+
/*
- * File status flags struture - shared for dup'ed fd's
+ * File status flags structure - shared for dup'ed fd's
*/
struct fs_flags {
int flags;
+#define _FD_NOTSOCK O_EXCL /* Not a socket. */
int refcnt;
SLIST_ENTRY(fs_flags) fe; /* free list entry. */
};
@@ -1152,6 +1157,7 @@ void _thread_dump_data(const void *, int);
void _thread_dump_info(void);
int _thread_fd_lock(int, int, struct timespec *);
void _thread_fd_unlock(int, int);
+struct timespec *_thread_fd_timeout(int, int);
void _thread_init(void);
void _thread_kern_lock(int);
void _thread_kern_sched(struct sigcontext *);
diff --git a/lib/libpthread/uthread/uthread_fcntl.c b/lib/libpthread/uthread/uthread_fcntl.c
index bf9f70e839c..864489b6e8d 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.9 2006/09/26 14:18:28 kurt Exp $ */
+/* $OpenBSD: uthread_fcntl.c,v 1.10 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -44,6 +44,7 @@ fcntl(int fd, int cmd,...)
{
int flags = 0;
int nonblock;
+ int notsock;
int oldfd;
int ret;
va_list ap;
@@ -87,7 +88,8 @@ fcntl(int fd, int cmd,...)
ret = _thread_sys_fcntl(fd, cmd, 0);
break;
case F_GETFL:
- ret = _thread_fd_table[fd]->status_flags->flags;
+ ret = _thread_fd_table[fd]->status_flags->flags &
+ ~_FD_NOTSOCK;
break;
case F_SETFL:
/*
@@ -102,8 +104,13 @@ fcntl(int fd, int cmd,...)
*/
nonblock = flags & O_NONBLOCK;
+ /* Remember the non-socket flag: */
+ notsock = _thread_fd_table[fd]->status_flags->flags &
+ _FD_NOTSOCK;
+
/* Set the file descriptor flags: */
- if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) != 0) {
+ if ((ret = _thread_sys_fcntl(fd, cmd,
+ flags | O_NONBLOCK)) != 0) {
/* Get the flags so that we behave like the kernel: */
} else if ((flags = _thread_sys_fcntl(fd,
@@ -117,10 +124,17 @@ fcntl(int fd, int cmd,...)
*/
} else if (nonblock)
/* A non-blocking descriptor: */
- _thread_fd_table[fd]->status_flags->flags = flags | O_NONBLOCK;
+ _thread_fd_table[fd]->status_flags->flags =
+ flags | O_NONBLOCK;
else
/* Save the flags: */
- _thread_fd_table[fd]->status_flags->flags = flags & ~O_NONBLOCK;
+ _thread_fd_table[fd]->status_flags->flags =
+ flags & ~O_NONBLOCK;
+
+ /* Restore if previously set: */
+ if (ret != -1 && notsock)
+ _thread_fd_table[fd]->status_flags->flags |=
+ _FD_NOTSOCK;
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 45db8fb8167..9816616a900 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.32 2009/12/06 17:54:59 kurt Exp $ */
+/* $OpenBSD: uthread_fd.c,v 1.33 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -33,11 +33,13 @@
* $FreeBSD: uthread_fd.c,v 1.13 1999/08/28 00:03:31 peter Exp $
*
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
@@ -724,7 +726,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
* Schedule this thread to wait on
* the read lock. It will only be
* woken when it becomes the next in
- * the queue and is granted access
+ * the queue and is granted access
* to the lock by the thread that is
* unlocking the file descriptor.
*/
@@ -839,4 +841,30 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
return (ret);
}
+struct timespec *
+_thread_fd_timeout(int fd, int which)
+{
+ struct timeval tv;
+ socklen_t len;
+ int saved_errno;
+
+ /* Avoid calling getsockopt if fd is not a socket. */
+ if (!(_thread_fd_table[fd]->status_flags->flags & _FD_NOTSOCK)) {
+ len = sizeof(tv);
+ saved_errno = errno;
+ if (_thread_sys_getsockopt(fd, SOL_SOCKET, which ?
+ SO_SNDTIMEO : SO_RCVTIMEO, &tv, &len) == 0) {
+ if (timerisset(&tv)) {
+ static struct timespec ts;
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ return (&ts);
+ }
+ } else if (errno == ENOTSOCK)
+ _thread_fd_table[fd]->status_flags->flags |=
+ _FD_NOTSOCK;
+ errno = saved_errno;
+ }
+ return (NULL);
+}
+
#endif
diff --git a/lib/libpthread/uthread/uthread_read.c b/lib/libpthread/uthread/uthread_read.c
index 9c3ef425c52..7cdf9adc08e 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.9 2006/10/03 02:59:36 kurt Exp $ */
+/* $OpenBSD: uthread_read.c,v 1.10 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -73,19 +73,20 @@ read(int fd, void *buf, size_t nbytes)
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);
+ _thread_kern_set_timeout(_FD_RCVTIMEO(fd));
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDR_WAIT,
__FILE__, __LINE__);
/*
* Check if the operation was
- * interrupted by a signal or
- * a closing fd.
+ * interrupted by a signal,
+ * a closing fd or timed out.
*/
if (curthread->interrupted) {
errno = EINTR;
@@ -95,6 +96,10 @@ read(int fd, void *buf, size_t nbytes)
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
break;
diff --git a/lib/libpthread/uthread/uthread_readv.c b/lib/libpthread/uthread/uthread_readv.c
index 7019df3af52..c152b0cfb77 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.9 2006/10/03 02:59:36 kurt Exp $ */
+/* $OpenBSD: uthread_readv.c,v 1.10 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -71,19 +71,20 @@ readv(int fd, const struct iovec * iov, int iovcnt)
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);
+ _thread_kern_set_timeout(_FD_RCVTIMEO(fd));
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDR_WAIT,
__FILE__, __LINE__);
/*
* Check if the operation was
- * interrupted by a signal or
- * a closing fd.
+ * interrupted by a signal,
+ * a closing fd or timed out.
*/
if (curthread->interrupted) {
errno = EINTR;
@@ -93,6 +94,10 @@ readv(int fd, const struct iovec * iov, int iovcnt)
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
break;
diff --git a/lib/libpthread/uthread/uthread_recvfrom.c b/lib/libpthread/uthread/uthread_recvfrom.c
index a76873fdf14..424ba6550b7 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.10 2009/04/11 20:26:58 jakemsr Exp $ */
+/* $OpenBSD: uthread_recvfrom.c,v 1.11 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -57,9 +57,10 @@ recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, sockl
curthread->data.fd.fd = fd;
/* Set the timeout: */
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_RCVTIMEO(fd));
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
/* Check if the wait was interrupted: */
@@ -73,6 +74,11 @@ recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, sockl
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ /* Return an error status: */
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_recvmsg.c b/lib/libpthread/uthread/uthread_recvmsg.c
index 4e14aad4549..66de9d14998 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.9 2009/04/11 20:26:58 jakemsr Exp $ */
+/* $OpenBSD: uthread_recvmsg.c,v 1.10 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -57,9 +57,10 @@ recvmsg(int fd, struct msghdr *msg, int flags)
curthread->data.fd.fd = fd;
/* Set the timeout: */
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_RCVTIMEO(fd));
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
/* Check if the wait was interrupted: */
@@ -73,6 +74,11 @@ recvmsg(int fd, struct msghdr *msg, int flags)
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ /* Return an error status: */
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_sendmsg.c b/lib/libpthread/uthread/uthread_sendmsg.c
index 8272ac91024..d0d1010d75b 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.8 2007/05/01 18:16:38 kurt Exp $ */
+/* $OpenBSD: uthread_sendmsg.c,v 1.9 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -56,9 +56,10 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
curthread->data.fd.fd = fd;
/* Set the timeout: */
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_SNDTIMEO(fd));
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
/* Check if the operation was interrupted: */
@@ -70,6 +71,10 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_sendto.c b/lib/libpthread/uthread/uthread_sendto.c
index a3eddc197f8..fc5aa5152b0 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.9 2007/05/01 18:16:38 kurt Exp $ */
+/* $OpenBSD: uthread_sendto.c,v 1.10 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -56,9 +56,10 @@ sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * t
curthread->data.fd.fd = fd;
/* Set the timeout: */
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_SNDTIMEO(fd));
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
/* Check if the operation was interrupted: */
@@ -70,6 +71,10 @@ sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * t
errno = EBADF;
ret = -1;
break;
+ } else if (curthread->timeout) {
+ errno = EWOULDBLOCK;
+ ret = -1;
+ break;
}
} else {
ret = -1;
diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c
index 8766470fc95..6d54c04744b 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.24 2007/05/18 19:28:50 kurt Exp $ */
+/* $OpenBSD: uthread_sig.c,v 1.25 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -189,7 +189,7 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
if (_thread_fd_table[i] != NULL &&
_thread_fd_table[i]->status_flags != NULL)
_thread_sys_fcntl(i, F_SETFL,
- _thread_fd_table[i]->status_flags->flags |
+ (_thread_fd_table[i]->status_flags->flags & ~_FD_NOTSOCK) |
O_NONBLOCK);
}
diff --git a/lib/libpthread/uthread/uthread_sigmask.c b/lib/libpthread/uthread/uthread_sigmask.c
index b33227e2aed..d44bfef7ae6 100644
--- a/lib/libpthread/uthread/uthread_sigmask.c
+++ b/lib/libpthread/uthread/uthread_sigmask.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sigmask.c,v 1.8 2008/04/24 03:31:33 kurt Exp $ */
+/* $OpenBSD: uthread_sigmask.c,v 1.9 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -80,7 +80,7 @@ pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
}
/*
- * Check if there are pending signals for the running
+ * Check if there are pending signals for the running
* thread or process that aren't blocked:
*/
sigset = curthread->sigpend;
diff --git a/lib/libpthread/uthread/uthread_write.c b/lib/libpthread/uthread/uthread_write.c
index ca1a99a7e78..642572022e9 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.13 2007/05/18 19:28:50 kurt Exp $ */
+/* $OpenBSD: uthread_write.c,v 1.14 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -104,11 +104,12 @@ write(int fd, const void *buf, size_t nbytes)
if (blocking && ((n < 0 && (errno == EWOULDBLOCK ||
errno == EAGAIN)) || (n > 0 && num < nbytes))) {
curthread->data.fd.fd = fd;
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_SNDTIMEO(fd));
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDW_WAIT,
__FILE__, __LINE__);
@@ -117,7 +118,9 @@ write(int fd, const void *buf, size_t nbytes)
* Check if the operation was
* interrupted by a signal
*/
- if (curthread->interrupted || curthread->closing_fd) {
+ if (curthread->interrupted ||
+ curthread->closing_fd ||
+ curthread->timeout) {
if (num > 0) {
/* Return partial success: */
ret = (ssize_t)num;
@@ -125,8 +128,10 @@ write(int fd, const void *buf, size_t nbytes)
/* Return an error: */
if (curthread->closing_fd)
errno = EBADF;
- else
+ else if (curthread->interrupted)
errno = EINTR;
+ else
+ errno = EWOULDBLOCK;
ret = -1;
}
}
diff --git a/lib/libpthread/uthread/uthread_writev.c b/lib/libpthread/uthread/uthread_writev.c
index 17850b0f875..6c3d41c14f4 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.13 2007/05/18 19:28:50 kurt Exp $ */
+/* $OpenBSD: uthread_writev.c,v 1.14 2010/01/03 23:05:35 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -175,11 +175,12 @@ writev(int fd, const struct iovec * iov, int iovcnt)
if (blocking && ((n < 0 && (errno == EWOULDBLOCK ||
errno == EAGAIN)) || (n >= 0 && idx < iovcnt))) {
curthread->data.fd.fd = fd;
- _thread_kern_set_timeout(NULL);
+ _thread_kern_set_timeout(_FD_SNDTIMEO(fd));
/* Reset the interrupted operation flag: */
curthread->interrupted = 0;
curthread->closing_fd = 0;
+ curthread->timeout = 0;
_thread_kern_sched_state(PS_FDW_WAIT,
__FILE__, __LINE__);
@@ -188,7 +189,9 @@ writev(int fd, const struct iovec * iov, int iovcnt)
* Check if the operation was
* interrupted by a signal
*/
- if (curthread->interrupted || curthread->closing_fd) {
+ if (curthread->interrupted ||
+ curthread->closing_fd ||
+ curthread->timeout) {
if (num > 0) {
/* Return partial success: */
ret = num;
@@ -196,8 +199,10 @@ writev(int fd, const struct iovec * iov, int iovcnt)
/* Return an error: */
if (curthread->closing_fd)
errno = EBADF;
- else
+ else if (curthread->interrupted)
errno = EINTR;
+ else
+ errno = EWOULDBLOCK;
ret = -1;
}
}