diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fc599bf36..c68ced329 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2013-12-01 Christopher Faylor + + * 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. + 2013-12-01 Corinna Vinschen * dtable.cc (dtable::extend): Change local variable new_size to size_t 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; } diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index f0e484c01..0ec7b3a75 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -34,8 +34,6 @@ class dtable static const int initial_archetype_size = 8; size_t first_fd_for_open; int cnt_need_fixup_before; - void lock () {lock_process::locker.acquire ();} - void unlock () {lock_process::locker.release ();} public: size_t size; @@ -87,15 +85,8 @@ public: void delete_archetype (fhandler_base *); void fixup_before_exec (DWORD win_proc_id); void fixup_before_fork (DWORD win_proc_id); - friend void dtable_init (); - friend void __stdcall close_all_files (bool); - friend int dup_finish (int, int, int); - friend class fhandler_base; - friend class cygheap_fdmanip; - friend class cygheap_fdget; - friend class cygheap_fdnew; - friend class cygheap_fdenum; - friend class lock_process; + void lock () {lock_process::locker.acquire ();} + void unlock () {lock_process::locker.release ();} }; fhandler_base *build_fh_dev (const device&, const char * = NULL);