summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/uthread/uthread_fd.c
diff options
context:
space:
mode:
authormarc <marc@openbsd.org>2003-02-14 03:58:42 +0000
committermarc <marc@openbsd.org>2003-02-14 03:58:42 +0000
commit04397332fe2f3ba54d8fe0b9d437fe75b9e1b00b (patch)
tree42c24a47ced6db25c16d7aab8a2bc7ac8dadbf43 /lib/libpthread/uthread/uthread_fd.c
parentwhite space (diff)
downloadwireguard-openbsd-04397332fe2f3ba54d8fe0b9d437fe75b9e1b00b.tar.xz
wireguard-openbsd-04397332fe2f3ba54d8fe0b9d437fe75b9e1b00b.zip
fix bug that would leave an FD locked if dup'd, then closed.
Also, for safety lock the _thread_fd_table when removing entries.
Diffstat (limited to 'lib/libpthread/uthread/uthread_fd.c')
-rw-r--r--lib/libpthread/uthread/uthread_fd.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/lib/libpthread/uthread/uthread_fd.c b/lib/libpthread/uthread/uthread_fd.c
index 4a48a8dd48c..ac81f56e1f1 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.20 2003/02/05 06:20:36 marc Exp $ */
+/* $OpenBSD: uthread_fd.c,v 1.21 2003/02/14 03:58:42 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -233,10 +233,8 @@ _thread_fd_table_dup(int from_fd, int to_fd)
entry = _thread_fd_table[to_fd];
if (entry != NULL) {
ret = _FD_LOCK(to_fd, FD_RDWR, NULL);
- if (ret != -1) {
- if (--entry->refcnt == 0)
- free(entry);
- }
+ if (ret != -1)
+ _thread_fd_table_remove(to_fd);
} else
ret = 0;
@@ -254,6 +252,26 @@ _thread_fd_table_dup(int from_fd, int to_fd)
}
/*
+ * Remove an fd entry from the table and free it if it's reference count
+ * goes to zero. The entry is assumed to be locked with a RDWR lock! It
+ * will be unlocked if it is not freed.
+ */
+void
+_thread_fd_table_remove(int fd)
+{
+ struct fd_table_entry *entry;
+
+ _SPINLOCK(&fd_table_lock);
+ entry = _thread_fd_table[fd];
+ if (--entry->refcnt == 0)
+ free(entry);
+ else
+ _FD_UNLOCK(fd, FD_RDWR);
+ _thread_fd_table[fd] = NULL;
+ _SPINUNLOCK(&fd_table_lock);
+}
+
+/*
* Unlock the fd table entry for a given thread, fd, and lock type.
*/
void