summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2008-06-03 14:45:06 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2008-06-03 14:45:06 +0000
commit4af9874148b61feb347eb59c1200da38653576c1 (patch)
treeb435ad4a013d336332b7c2542765b8c2d4276f67
parente70f08b5652c86aa41ffd6d501e1cd28172dc64b (diff)
Don't grab the fd read lock for getsockopt(2), setsockopt(2),
getpeername(2) or getsockname(2). Its not needed and causes threads to block when another thread is blocked and holding the read lock. Instead just protect against fd state transitions. Blocking problem reported by David S H Rosenthal from lockss.org okay beck@ "looks sane" deraadt@
-rw-r--r--lib/libpthread/uthread/uthread_getpeername.c22
-rw-r--r--lib/libpthread/uthread/uthread_getsockname.c22
-rw-r--r--lib/libpthread/uthread/uthread_getsockopt.c20
-rw-r--r--lib/libpthread/uthread/uthread_setsockopt.c20
4 files changed, 66 insertions, 18 deletions
diff --git a/lib/libpthread/uthread/uthread_getpeername.c b/lib/libpthread/uthread/uthread_getpeername.c
index 378f23f7416..7a026a6885c 100644
--- a/lib/libpthread/uthread/uthread_getpeername.c
+++ b/lib/libpthread/uthread/uthread_getpeername.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_getpeername.c,v 1.4 1999/11/25 07:01:36 d Exp $ */
+/* $OpenBSD: uthread_getpeername.c,v 1.5 2008/06/03 14:45:05 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -32,6 +32,7 @@
*
* $FreeBSD: uthread_getpeername.c,v 1.5 1999/08/28 00:03:34 peter Exp $
*/
+#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef _THREAD_SAFE
@@ -41,12 +42,23 @@
int
getpeername(int fd, struct sockaddr * peer, socklen_t *paddrlen)
{
- int ret;
+ int ret;
+ struct fd_table_entry *entry;
- if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
- ret = _thread_sys_getpeername(fd, peer, paddrlen);
- _FD_UNLOCK(fd, FD_READ);
+ ret = _thread_fd_table_init(fd, FD_INIT_UNKNOWN, NULL);
+ if (ret == 0) {
+ entry = _thread_fd_table[fd];
+
+ _SPINLOCK(&entry->lock);
+ if (entry->state == FD_ENTRY_OPEN) {
+ ret = _thread_sys_getpeername(fd, peer, paddrlen);
+ } else {
+ ret = -1;
+ errno = EBADF;
+ }
+ _SPINUNLOCK(&entry->lock);
}
+
return ret;
}
#endif
diff --git a/lib/libpthread/uthread/uthread_getsockname.c b/lib/libpthread/uthread/uthread_getsockname.c
index 683cc910f15..22ad8075c8e 100644
--- a/lib/libpthread/uthread/uthread_getsockname.c
+++ b/lib/libpthread/uthread/uthread_getsockname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_getsockname.c,v 1.4 1999/11/25 07:01:36 d Exp $ */
+/* $OpenBSD: uthread_getsockname.c,v 1.5 2008/06/03 14:45:05 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -32,6 +32,7 @@
*
* $FreeBSD: uthread_getsockname.c,v 1.5 1999/08/28 00:03:36 peter Exp $
*/
+#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef _THREAD_SAFE
@@ -39,14 +40,25 @@
#include "pthread_private.h"
int
-getsockname(int s, struct sockaddr * name, socklen_t *namelen)
+getsockname(int fd, struct sockaddr * name, socklen_t *namelen)
{
int ret;
+ struct fd_table_entry *entry;
- if ((ret = _FD_LOCK(s, FD_READ, NULL)) == 0) {
- ret = _thread_sys_getsockname(s, name, namelen);
- _FD_UNLOCK(s, FD_READ);
+ ret = _thread_fd_table_init(fd, FD_INIT_UNKNOWN, NULL);
+ if (ret == 0) {
+ entry = _thread_fd_table[fd];
+
+ _SPINLOCK(&entry->lock);
+ if (entry->state == FD_ENTRY_OPEN) {
+ ret = _thread_sys_getsockname(fd, name, namelen);
+ } else {
+ ret = -1;
+ errno = EBADF;
+ }
+ _SPINUNLOCK(&entry->lock);
}
+
return ret;
}
#endif
diff --git a/lib/libpthread/uthread/uthread_getsockopt.c b/lib/libpthread/uthread/uthread_getsockopt.c
index f73b54780ea..09d31955652 100644
--- a/lib/libpthread/uthread/uthread_getsockopt.c
+++ b/lib/libpthread/uthread/uthread_getsockopt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_getsockopt.c,v 1.4 1999/11/25 07:01:36 d Exp $ */
+/* $OpenBSD: uthread_getsockopt.c,v 1.5 2008/06/03 14:45:05 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -32,6 +32,7 @@
*
* $FreeBSD: uthread_getsockopt.c,v 1.5 1999/08/28 00:03:36 peter Exp $
*/
+#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef _THREAD_SAFE
@@ -42,11 +43,22 @@ int
getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen)
{
int ret;
+ struct fd_table_entry *entry;
- if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) {
- ret = _thread_sys_getsockopt(fd, level, optname, optval, optlen);
- _FD_UNLOCK(fd, FD_RDWR);
+ ret = _thread_fd_table_init(fd, FD_INIT_UNKNOWN, NULL);
+ if (ret == 0) {
+ entry = _thread_fd_table[fd];
+
+ _SPINLOCK(&entry->lock);
+ if (entry->state == FD_ENTRY_OPEN) {
+ ret = _thread_sys_getsockopt(fd, level, optname, optval, optlen);
+ } else {
+ ret = -1;
+ errno = EBADF;
+ }
+ _SPINUNLOCK(&entry->lock);
}
+
return ret;
}
#endif
diff --git a/lib/libpthread/uthread/uthread_setsockopt.c b/lib/libpthread/uthread/uthread_setsockopt.c
index 77cda0a65c1..bf6041985be 100644
--- a/lib/libpthread/uthread/uthread_setsockopt.c
+++ b/lib/libpthread/uthread/uthread_setsockopt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_setsockopt.c,v 1.4 1999/11/25 07:01:44 d Exp $ */
+/* $OpenBSD: uthread_setsockopt.c,v 1.5 2008/06/03 14:45:05 kurt Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -32,6 +32,7 @@
*
* $FreeBSD: uthread_setsockopt.c,v 1.5 1999/08/28 00:03:47 peter Exp $
*/
+#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef _THREAD_SAFE
@@ -42,11 +43,22 @@ int
setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
{
int ret;
+ struct fd_table_entry *entry;
- if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) {
- ret = _thread_sys_setsockopt(fd, level, optname, optval, optlen);
- _FD_UNLOCK(fd, FD_RDWR);
+ ret = _thread_fd_table_init(fd, FD_INIT_UNKNOWN, NULL);
+ if (ret == 0) {
+ entry = _thread_fd_table[fd];
+
+ _SPINLOCK(&entry->lock);
+ if (entry->state == FD_ENTRY_OPEN) {
+ ret = _thread_sys_setsockopt(fd, level, optname, optval, optlen);
+ } else {
+ ret = -1;
+ errno = EBADF;
+ }
+ _SPINUNLOCK(&entry->lock);
}
+
return ret;
}
#endif