* 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.
This commit is contained in:
Corinna Vinschen 2009-07-22 15:46:36 +00:00
parent 1e497ebd33
commit 4a77aea071
4 changed files with 35 additions and 7 deletions

View File

@ -1,3 +1,15 @@
2009-07-21 Corinna Vinschen <corinna@vinschen.de>
* 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 <ebb9@byu.net>
* dtable.cc (dup2): Correct return value for no-op.

View File

@ -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

View File

@ -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)));

View File

@ -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);