diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e12bd85c9..e82125c1f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,15 @@ +2009-07-21 Corinna Vinschen + + * fhandler.h (enum del_lock_called_from): New enumeration. + (fhandler_base::del_my_locks): Declare taking a del_lock_called_from + as argument. + * fhandler.cc (fhandler_base::close): Call del_my_locks with "on_close". + (fhandler_base::fixup_after_fork): Call del_my_locks with "after_fork". + (fhandler_base::fixup_after_exec): Call del_my_locks with "after_exec". + * flock.cc (fhandler_base::del_my_locks): Take del_lock_called_from + as argument. Call node->del_my_locks with NULL handle in after_exec + case. Explain why. + 2009-07-21 Eric Blake * dtable.cc (dup2): Correct return value for no-op. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index ffbd02ffa..9ba286ec0 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1,7 +1,7 @@ /* fhandler.cc. See console.cc for fhandler_console functions. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. This file is part of Cygwin. @@ -1034,7 +1034,7 @@ fhandler_base::close () /* Delete all POSIX locks on the file. Delete all flock locks on the file if this is the last reference to this file. */ if (unique_id) - del_my_locks (false); + del_my_locks (on_close); if (nohandle () || CloseHandle (get_handle ())) res = 0; else @@ -1359,7 +1359,7 @@ fhandler_base::fixup_after_fork (HANDLE parent) setup_overlapped (); /* POSIX locks are not inherited across fork. */ if (unique_id) - del_my_locks (true); + del_my_locks (after_fork); } void @@ -1369,7 +1369,7 @@ fhandler_base::fixup_after_exec () if (get_overlapped ()) setup_overlapped (); if (unique_id && close_on_exec ()) - del_my_locks (false); + del_my_locks (after_exec); } bool diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 465924190..4995d15b2 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -93,6 +93,12 @@ enum query_state { query_write_attributes = 4 }; +enum del_lock_called_from { + on_close, + after_fork, + after_exec +}; + class fhandler_base { friend class dtable; @@ -141,7 +147,7 @@ class fhandler_base /* Used for advisory file locking. See flock.cc. */ long long unique_id; - void del_my_locks (bool); + void del_my_locks (del_lock_called_from); HANDLE read_state; int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3))); diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc index 72b9ef447..92b03d51e 100644 --- a/winsup/cygwin/flock.cc +++ b/winsup/cygwin/flock.cc @@ -344,14 +344,24 @@ inode_t::del_my_locks (long long id, HANDLE fhdl) case the close_on_exec flag is set. The whole inode is deleted as soon as no lock exists on it anymore. */ void -fhandler_base::del_my_locks (bool after_fork) +fhandler_base::del_my_locks (del_lock_called_from from) { INODE_LIST_LOCK (); inode_t *node = inode_t::get (get_dev (), get_ino (), false); if (node) { + /* When we're called from fixup_after_exec, the fhandler is a + close-on-exec fhandler. In this case our io handle is already + invalid. We can't use it to test for the object reference count. + However, that shouldn't be necessary for the following reason. + After exec, there are no threads in the current process waiting for + the lock. So, either we're the only process accessing the file table + entry and there are no threads which require signalling, or we have + a parent process still accessing the file object and signalling the + lock event would be premature. */ bool no_locks_left = - node->del_my_locks (after_fork ? 0 : get_unique_id (), get_handle ()); + node->del_my_locks (from == after_fork ? 0 : get_unique_id (), + from == after_exec ? NULL : get_handle ()); if (no_locks_left) { LIST_REMOVE (node, i_next);