diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2006-10-17 20:57:29 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2006-10-17 20:57:29 +0000 |
commit | e8d3b6a8553a5f79a00b959f9a6e7211edadc424 (patch) | |
tree | b4df683a68f7d7c48a3daa52cc8317361a3d0339 /lib | |
parent | 2a11b595da5be15d0b96062f21c6b158c2afa031 (diff) |
Don't grab _FD_LOCK and queue up behind other threads as
this can potentially block indefinitely. Instead just
protect against fd state transitions and perform
the _thread_sys_shutdown(). Fixes deadlock reported by
Tero Koskinen <tero.koskinen at iki.fi>. okay kettenis@
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libpthread/uthread/uthread_shutdown.c | 35 |
1 files changed, 13 insertions, 22 deletions
diff --git a/lib/libpthread/uthread/uthread_shutdown.c b/lib/libpthread/uthread/uthread_shutdown.c index b3219ec73a5..e8f3e776afb 100644 --- a/lib/libpthread/uthread/uthread_shutdown.c +++ b/lib/libpthread/uthread/uthread_shutdown.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_shutdown.c,v 1.4 2003/02/14 02:34:16 marc Exp $ */ +/* $OpenBSD: uthread_shutdown.c,v 1.5 2006/10/17 20:57:28 kurt Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -43,31 +43,22 @@ int shutdown(int fd, int how) { int ret; + struct fd_table_entry *entry; - switch (how) { - case 0: - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + 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_shutdown(fd, how); - _FD_UNLOCK(fd, FD_READ); + } else { + ret = -1; + errno = EBADF; } - break; - case 1: - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { - ret = _thread_sys_shutdown(fd, how); - _FD_UNLOCK(fd, FD_WRITE); - } - break; - case 2: - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { - ret = _thread_sys_shutdown(fd, how); - _FD_UNLOCK(fd, FD_RDWR); - } - break; - default: - errno = EBADF; - ret = -1; - break; + _SPINUNLOCK(&entry->lock); } + return (ret); } #endif |