diff options
author | Christopher Faylor <me@cgf.cx> | 2013-12-01 21:52:48 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2013-12-01 21:52:48 +0400 |
commit | f456b9f6f8efcb1e7472d31860b5815ccd614aa4 (patch) | |
tree | c263f4fab9d502e46cea61f8254fbbc088a274e7 /winsup/cygwin/dtable.cc | |
parent | 10a5939224465e3feb8e19208f187904000a0c38 (diff) |
* dtable.cc (dtable::find_unused_handle): Fix off-by-one error. Always exit
through the bottom.
(cygwin_attach_handle_to_fd): Make sure that fd tab is locked for the duration
of this function.
* dtable.h (dtable::lock): Make public.
(dtable::unlock): Ditto.
(dtable): Remove friends.
Diffstat (limited to 'winsup/cygwin/dtable.cc')
-rw-r--r-- | winsup/cygwin/dtable.cc | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 3934e008a..485e79c5d 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -223,17 +223,22 @@ dtable::delete_archetype (fhandler_base *fh) int dtable::find_unused_handle (size_t start) { - size_t extendby = (start > size) ? start - size : NOFILE_INCR; + size_t extendby = (start >= size) ? 1 + start - size : NOFILE_INCR; + /* This do loop should only ever execute twice. */ + int res = -1; do { for (size_t i = start; i < size; i++) /* See if open -- no need for overhead of not_open */ if (fds[i] == NULL) - return i; + { + res = (int) i; + break; + } } while (extend (extendby)); - return -1; + return res; } void @@ -251,14 +256,19 @@ extern "C" int cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin, DWORD myaccess) { + cygheap->fdtab.lock (); if (fd == -1) fd = cygheap->fdtab.find_unused_handle (); fhandler_base *fh = build_fh_name (name); if (!fh) - return -1; - cygheap->fdtab[fd] = fh; - cygheap->fdtab[fd]->inc_refcnt (); - fh->init (handle, myaccess, bin ?: fh->pc_binmode ()); + fd = -1; + else + { + cygheap->fdtab[fd] = fh; + cygheap->fdtab[fd]->inc_refcnt (); + fh->init (handle, myaccess, bin ?: fh->pc_binmode ()); + } + cygheap->fdtab.unlock (); return fd; } |