diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2010-01-03 23:05:36 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2010-01-03 23:05:36 +0000 |
commit | 8028f6a67fe786e34cdc97e0f80c7fe8ce12194b (patch) | |
tree | dfd309174b9fe946bc94a645173a2e5b6bd67b6b /lib | |
parent | 8977d0817d5af955632b410a7411fb89d1143f34 (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.h | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_fcntl.c | 24 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_fd.c | 34 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_read.c | 13 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_readv.c | 13 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_recvfrom.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_recvmsg.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sendmsg.c | 9 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sendto.c | 9 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sig.c | 4 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sigmask.c | 4 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_write.c | 13 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_writev.c | 13 |
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; } } |