* fhandler.cc (fhandler_base::open): Fix typo in comment.
(fhandler_base::close): Move call to del_my_locks from here... * fhandler_disk_file.cc (fhandler_disk_file::open): ...to here. * flock.cc (struct lockfattr_t): New type. (lockf_t::close_lock_obj): New method, use throughout. (lockf_t::create_lock_obj_attr): New method. (lockf_t::create_lock_obj): Use create_lock_obj_attr method. Handle STATUS_OBJECT_NAME_COLLISION in F_FLOCK case gracefully. Add lengthy comments to explain why and how. (lockf_t::open_lock_obj): Use create_lock_obj_attr method. (lockf_t::del_lock_obj): Call NtSetEvent rather than SetEvent for symmetry. (fhandler_disk_file::lock): Define n only where it's used. Call need_fork_fixup only if call was successful. Handle EINTR and ECANCELED return values from lf_setlock. (lf_setlock): Drop WAIT_UNLOCKED and WAIT_PROC_EXITED. Don't wait for event object handle count to become <= 1 in F_LOCK case. Simplify WFMO return value handling. Don't handle signal and cancel events here; just return with appropriate error code instead. (lf_getblock): Ignore locks for which the handle can't be opened. Use IsEventSignalled. * ntdll.h (STATUS_INVALID_INFO_CLASS): Undef if defined elsewhere to make sure the definition is casted to NTSTATUS. (STATUS_INVALID_HANDLE): Define and ditto. (STATUS_OBJECT_NAME_COLLISION): Define. (NtSetEvent): Declare.
This commit is contained in:
parent
477215fe7d
commit
f4ec874328
|
@ -1,3 +1,32 @@
|
||||||
|
2011-08-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler.cc (fhandler_base::open): Fix typo in comment.
|
||||||
|
(fhandler_base::close): Move call to del_my_locks from here...
|
||||||
|
* fhandler_disk_file.cc (fhandler_disk_file::open): ...to here.
|
||||||
|
* flock.cc (struct lockfattr_t): New type.
|
||||||
|
(lockf_t::close_lock_obj): New method, use throughout.
|
||||||
|
(lockf_t::create_lock_obj_attr): New method.
|
||||||
|
(lockf_t::create_lock_obj): Use create_lock_obj_attr method. Handle
|
||||||
|
STATUS_OBJECT_NAME_COLLISION in F_FLOCK case gracefully. Add lengthy
|
||||||
|
comments to explain why and how.
|
||||||
|
(lockf_t::open_lock_obj): Use create_lock_obj_attr method.
|
||||||
|
(lockf_t::del_lock_obj): Call NtSetEvent rather than SetEvent for
|
||||||
|
symmetry.
|
||||||
|
(fhandler_disk_file::lock): Define n only where it's used. Call
|
||||||
|
need_fork_fixup only if call was successful. Handle EINTR and
|
||||||
|
ECANCELED return values from lf_setlock.
|
||||||
|
(lf_setlock): Drop WAIT_UNLOCKED and WAIT_PROC_EXITED. Don't wait
|
||||||
|
for event object handle count to become <= 1 in F_LOCK case.
|
||||||
|
Simplify WFMO return value handling. Don't handle signal and cancel
|
||||||
|
events here; just return with appropriate error code instead.
|
||||||
|
(lf_getblock): Ignore locks for which the handle can't be opened.
|
||||||
|
Use IsEventSignalled.
|
||||||
|
* ntdll.h (STATUS_INVALID_INFO_CLASS): Undef if defined elsewhere to
|
||||||
|
make sure the definition is casted to NTSTATUS.
|
||||||
|
(STATUS_INVALID_HANDLE): Define and ditto.
|
||||||
|
(STATUS_OBJECT_NAME_COLLISION): Define.
|
||||||
|
(NtSetEvent): Declare.
|
||||||
|
|
||||||
2011-08-25 Rafal Zwierz <rzwierz@googlemail.com>
|
2011-08-25 Rafal Zwierz <rzwierz@googlemail.com>
|
||||||
|
|
||||||
* cygthread.cc (cygthread::simplestub): Notify that the thread has
|
* cygthread.cc (cygthread::simplestub): Notify that the thread has
|
||||||
|
|
|
@ -672,7 +672,7 @@ fhandler_base::open (int flags, mode_t mode)
|
||||||
status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi,
|
status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi,
|
||||||
FileEndOfFileInformation);
|
FileEndOfFileInformation);
|
||||||
/* In theory, truncating the file should never fail, since the opened
|
/* In theory, truncating the file should never fail, since the opened
|
||||||
handle has FILE_READ_DATA permissions, which is all you need to
|
handle has FILE_WRITE_DATA permissions, which is all you need to
|
||||||
be allowed to truncate a file. Better safe than sorry. */
|
be allowed to truncate a file. Better safe than sorry. */
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
|
@ -1130,10 +1130,6 @@ fhandler_base::close ()
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
|
syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
|
||||||
/* 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 (on_close);
|
|
||||||
if (nohandle () || CloseHandle (get_handle ()))
|
if (nohandle () || CloseHandle (get_handle ()))
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
|
|
|
@ -1380,8 +1380,12 @@ fhandler_disk_file::open (int flags, mode_t mode)
|
||||||
int
|
int
|
||||||
fhandler_disk_file::close ()
|
fhandler_disk_file::close ()
|
||||||
{
|
{
|
||||||
|
/* Close extra pread/pwrite handle, if it exists. */
|
||||||
if (prw_handle)
|
if (prw_handle)
|
||||||
NtClose (prw_handle);
|
NtClose (prw_handle);
|
||||||
|
/* Delete all POSIX locks on the file. Delete all flock locks on the
|
||||||
|
file if this is the last reference to this file. */
|
||||||
|
del_my_locks (on_close);
|
||||||
return fhandler_base::close ();
|
return fhandler_base::close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
#include "sigproc.h"
|
#include "sigproc.h"
|
||||||
#include "cygtls.h"
|
#include "cygtls.h"
|
||||||
#include "tls_pbuf.h"
|
#include "tls_pbuf.h"
|
||||||
|
#include "miscfuncs.h"
|
||||||
#include "ntdll.h"
|
#include "ntdll.h"
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
@ -212,21 +213,29 @@ get_obj_handle_count (HANDLE h)
|
||||||
return hdl_cnt;
|
return hdl_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper struct to construct a local OBJECT_ATTRIBUTES on the stack. */
|
||||||
|
struct lockfattr_t
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
UNICODE_STRING uname;
|
||||||
|
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
|
||||||
|
};
|
||||||
|
|
||||||
/* Per lock class. */
|
/* Per lock class. */
|
||||||
class lockf_t
|
class lockf_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
|
short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
|
||||||
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
||||||
_off64_t lf_start; /* Byte # of the start of the lock */
|
_off64_t lf_start; /* Byte # of the start of the lock */
|
||||||
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
|
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
|
||||||
long long lf_id; /* Cygwin PID for POSIX locks, a unique id per
|
long long lf_id; /* Cygwin PID for POSIX locks, a unique id per
|
||||||
file table entry for BSD flock locks. */
|
file table entry for BSD flock locks. */
|
||||||
DWORD lf_wid; /* Win PID of the resource holding the lock */
|
DWORD lf_wid; /* Win PID of the resource holding the lock */
|
||||||
class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */
|
class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */
|
||||||
class inode_t *lf_inode; /* Back pointer to the inode_t */
|
class inode_t *lf_inode; /* Back pointer to the inode_t */
|
||||||
class lockf_t *lf_next; /* Pointer to the next lock on this inode_t */
|
class lockf_t *lf_next; /* Pointer to the next lock on this inode_t */
|
||||||
HANDLE lf_obj; /* Handle to the lock event object. */
|
HANDLE lf_obj; /* Handle to the lock event object. */
|
||||||
|
|
||||||
lockf_t ()
|
lockf_t ()
|
||||||
: lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0),
|
: lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0),
|
||||||
|
@ -251,8 +260,12 @@ class lockf_t
|
||||||
void operator delete (void *p)
|
void operator delete (void *p)
|
||||||
{ cfree (p); }
|
{ cfree (p); }
|
||||||
|
|
||||||
|
POBJECT_ATTRIBUTES create_lock_obj_attr (lockfattr_t *attr,
|
||||||
|
ULONG flags);
|
||||||
|
|
||||||
void create_lock_obj ();
|
void create_lock_obj ();
|
||||||
bool open_lock_obj ();
|
bool open_lock_obj ();
|
||||||
|
void close_lock_obj () { NtClose (lf_obj); lf_obj = NULL; }
|
||||||
void del_lock_obj (HANDLE fhdl, bool signal = false);
|
void del_lock_obj (HANDLE fhdl, bool signal = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -542,47 +555,72 @@ inode_t::get_all_locks_list ()
|
||||||
return i_all_lf;
|
return i_all_lf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the lock object name. The name is constructed from the lock
|
||||||
|
properties which identify it uniquely, all values in hex. */
|
||||||
|
POBJECT_ATTRIBUTES
|
||||||
|
lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
|
||||||
|
{
|
||||||
|
__small_swprintf (attr->name, L"%02x-%01x-%016X-%016X-%016X-%08x",
|
||||||
|
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, lf_end,
|
||||||
|
lf_id, lf_wid);
|
||||||
|
RtlInitCountedUnicodeString (&attr->uname, attr->name,
|
||||||
|
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
|
||||||
|
InitializeObjectAttributes (&attr->attr, &attr->uname, flags, lf_inode->i_dir,
|
||||||
|
everyone_sd (FLOCK_EVENT_ACCESS));
|
||||||
|
return &attr->attr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the lock event object in the file's subdir in the NT global
|
/* Create the lock event object in the file's subdir in the NT global
|
||||||
namespace. The name is constructed from the lock properties which
|
namespace. */
|
||||||
identify it uniquely, all values in hex. See the __small_swprintf
|
|
||||||
call right at the start. */
|
|
||||||
void
|
void
|
||||||
lockf_t::create_lock_obj ()
|
lockf_t::create_lock_obj ()
|
||||||
{
|
{
|
||||||
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
|
lockfattr_t attr;
|
||||||
UNICODE_STRING uname;
|
|
||||||
OBJECT_ATTRIBUTES attr;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x",
|
do
|
||||||
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
{
|
||||||
lf_end, lf_id, lf_wid);
|
status = NtCreateEvent (&lf_obj, CYG_EVENT_ACCESS,
|
||||||
RtlInitCountedUnicodeString (&uname, name,
|
create_lock_obj_attr (&attr, OBJ_INHERIT),
|
||||||
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
|
NotificationEvent, FALSE);
|
||||||
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, lf_inode->i_dir,
|
if (!NT_SUCCESS (status))
|
||||||
everyone_sd (FLOCK_EVENT_ACCESS));
|
{
|
||||||
status = NtCreateEvent (&lf_obj, CYG_EVENT_ACCESS, &attr,
|
if (status != STATUS_OBJECT_NAME_COLLISION || (lf_flags & F_POSIX))
|
||||||
NotificationEvent, FALSE);
|
api_fatal ("NtCreateEvent(lock): %p", status);
|
||||||
if (!NT_SUCCESS (status))
|
/* If we get a STATUS_OBJECT_NAME_COLLISION in the F_FLOCK case, the
|
||||||
api_fatal ("NtCreateEvent(lock): %p", status);
|
event still exists because some other process is waiting for it
|
||||||
|
in lf_setlock. If so, open the event and check the signal state.
|
||||||
|
If we can't open it, it has been closed in the meantime, so just
|
||||||
|
try again. If we can open it and the object is not signalled,
|
||||||
|
it's surely a bug in the code somewhere. Otherwise, close the
|
||||||
|
event and retry to create an event with another name. */
|
||||||
|
if (open_lock_obj ())
|
||||||
|
{
|
||||||
|
if (!IsEventSignalled (lf_obj))
|
||||||
|
api_fatal ("NtCreateEvent(lock): %p", status);
|
||||||
|
close_lock_obj ();
|
||||||
|
/* Change the lf_wid member to generate another name for the
|
||||||
|
event, so as not to colide with the still-in-use event.
|
||||||
|
Changing lf_wid is ok, because the Windows PID is not used
|
||||||
|
for synchronization in the F_FLOCK case.
|
||||||
|
What we do here is to increment the highest byte in lf_wid. */
|
||||||
|
lf_wid = ((lf_wid & 0xff000000) + (1 << 24))
|
||||||
|
| (lf_wid & 0xffffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!NT_SUCCESS (status));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
||||||
bool
|
bool
|
||||||
lockf_t::open_lock_obj ()
|
lockf_t::open_lock_obj ()
|
||||||
{
|
{
|
||||||
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
|
lockfattr_t attr;
|
||||||
UNICODE_STRING uname;
|
|
||||||
OBJECT_ATTRIBUTES attr;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x",
|
status = NtOpenEvent (&lf_obj, FLOCK_EVENT_ACCESS,
|
||||||
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
create_lock_obj_attr (&attr, 0));
|
||||||
lf_end, lf_id, lf_wid);
|
|
||||||
RtlInitCountedUnicodeString (&uname, name,
|
|
||||||
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
|
|
||||||
InitializeObjectAttributes (&attr, &uname, 0, lf_inode->i_dir, NULL);
|
|
||||||
status = NtOpenEvent (&lf_obj, FLOCK_EVENT_ACCESS, &attr);
|
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
SetLastError (RtlNtStatusToDosError (status));
|
SetLastError (RtlNtStatusToDosError (status));
|
||||||
|
@ -591,9 +629,9 @@ lockf_t::open_lock_obj ()
|
||||||
return lf_obj != NULL;
|
return lf_obj != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a lock event handle. The important thing here is to signal it
|
/* Delete a lock event handle. The important thing here is to signal it
|
||||||
before closing the handle. This way all threads waiting for this
|
before closing the handle. This way all threads waiting for this lock
|
||||||
lock can wake up. */
|
can wake up. */
|
||||||
void
|
void
|
||||||
lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
|
lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
|
||||||
{
|
{
|
||||||
|
@ -608,9 +646,8 @@ lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
|
||||||
handle/descriptor to the same FILE_OBJECT/file table entry. */
|
handle/descriptor to the same FILE_OBJECT/file table entry. */
|
||||||
if ((lf_flags & F_POSIX) || signal
|
if ((lf_flags & F_POSIX) || signal
|
||||||
|| (fhdl && get_obj_handle_count (fhdl) <= 1))
|
|| (fhdl && get_obj_handle_count (fhdl) <= 1))
|
||||||
SetEvent (lf_obj);
|
NtSetEvent (lf_obj, NULL);
|
||||||
NtClose (lf_obj);
|
close_lock_obj ();
|
||||||
lf_obj = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +680,6 @@ int
|
||||||
fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
{
|
{
|
||||||
_off64_t start, end, oadd;
|
_off64_t start, end, oadd;
|
||||||
lockf_t *n;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
|
short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
|
||||||
|
@ -758,13 +794,14 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
end = start + oadd;
|
end = start + oadd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restart: /* Entry point after a restartable signal came in. */
|
||||||
|
|
||||||
inode_t *node = inode_t::get (get_dev (), get_ino (), true);
|
inode_t *node = inode_t::get (get_dev (), get_ino (), true);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
set_errno (ENOLCK);
|
set_errno (ENOLCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
need_fork_fixup (true);
|
|
||||||
|
|
||||||
/* Unlock the fd table which has been locked in fcntl_worker/lock_worker,
|
/* Unlock the fd table which has been locked in fcntl_worker/lock_worker,
|
||||||
otherwise a blocking F_SETLKW never wakes up on a signal. */
|
otherwise a blocking F_SETLKW never wakes up on a signal. */
|
||||||
|
@ -844,7 +881,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
}
|
}
|
||||||
for (lock = clean; lock != NULL; )
|
for (lock = clean; lock != NULL; )
|
||||||
{
|
{
|
||||||
n = lock->lf_next;
|
lockf_t *n = lock->lf_next;
|
||||||
lock->del_lock_obj (get_handle (), a_op == F_UNLCK);
|
lock->del_lock_obj (get_handle (), a_op == F_UNLCK);
|
||||||
delete lock;
|
delete lock;
|
||||||
lock = n;
|
lock = n;
|
||||||
|
@ -859,12 +896,23 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
node->UNLOCK ();
|
node->UNLOCK ();
|
||||||
if (error)
|
switch (error)
|
||||||
{
|
{
|
||||||
set_errno (error);
|
case 0: /* All is well. */
|
||||||
return -1;
|
need_fork_fixup (true);
|
||||||
|
return 0;
|
||||||
|
case EINTR: /* Signal came in. */
|
||||||
|
if (_my_tls.call_signal_handler ())
|
||||||
|
goto restart;
|
||||||
|
break;
|
||||||
|
case ECANCELED: /* The thread has been sent a cancellation request. */
|
||||||
|
pthread::static_cancel_self ();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
set_errno (error);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -961,10 +1009,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
|
||||||
HANDLE cancel_event = pthread::get_cancel_event ();
|
HANDLE cancel_event = pthread::get_cancel_event ();
|
||||||
|
|
||||||
int wait_count = 0;
|
int wait_count = 0;
|
||||||
/* The lock is always the first object. */
|
/* The lock event is always the first object, all other wait objects
|
||||||
const DWORD WAIT_UNLOCKED = WAIT_OBJECT_0;
|
are variable. */
|
||||||
/* All other wait objects are variable. */
|
|
||||||
DWORD WAIT_PROC_EXITED = WAIT_TIMEOUT + 1;
|
|
||||||
DWORD WAIT_SIGNAL_ARRIVED = WAIT_TIMEOUT + 1;
|
DWORD WAIT_SIGNAL_ARRIVED = WAIT_TIMEOUT + 1;
|
||||||
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
|
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
|
||||||
|
|
||||||
|
@ -985,7 +1031,6 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
|
||||||
|
|
||||||
HANDLE w4[4] = { obj, proc, signal_arrived, cancel_event };
|
HANDLE w4[4] = { obj, proc, signal_arrived, cancel_event };
|
||||||
wait_count = 3;
|
wait_count = 3;
|
||||||
WAIT_PROC_EXITED = WAIT_OBJECT_0 + 1;
|
|
||||||
WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 2;
|
WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 2;
|
||||||
if (cancel_event)
|
if (cancel_event)
|
||||||
{
|
{
|
||||||
|
@ -1012,45 +1057,34 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
|
||||||
node->UNLOCK ();
|
node->UNLOCK ();
|
||||||
/* Unfortunately, since BSD flock locks are not attached to a
|
/* Unfortunately, since BSD flock locks are not attached to a
|
||||||
specific process, we can't recognize an abandoned lock by
|
specific process, we can't recognize an abandoned lock by
|
||||||
sync'ing with a process. We have to find out if we're the only
|
sync'ing with a process. We have to make sure we're the only
|
||||||
process left accessing this event object. */
|
process left accessing this event object, or that the event
|
||||||
do
|
object is in a signalled state. */
|
||||||
{
|
ret = WaitForMultipleObjects (wait_count, w4, FALSE, 100L);
|
||||||
ret = WaitForMultipleObjects (wait_count, w4, FALSE, 100L);
|
|
||||||
}
|
|
||||||
while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1);
|
|
||||||
/* There's a good chance that the above loop is left with
|
|
||||||
ret == WAIT_TIMEOUT if another process closes the file handle
|
|
||||||
associated with this lock. This is for all practical purposes
|
|
||||||
equivalent to a signalled lock object. */
|
|
||||||
if (ret == WAIT_TIMEOUT)
|
|
||||||
ret = WAIT_OBJECT_0;
|
|
||||||
}
|
}
|
||||||
node->LOCK ();
|
node->LOCK ();
|
||||||
node->unwait ();
|
node->unwait ();
|
||||||
NtClose (obj);
|
NtClose (obj);
|
||||||
SetThreadPriority (GetCurrentThread (), old_prio);
|
SetThreadPriority (GetCurrentThread (), old_prio);
|
||||||
if (ret == WAIT_UNLOCKED)
|
if (ret == WAIT_SIGNAL_ARRIVED)
|
||||||
; /* The lock object has been set to signalled. */
|
|
||||||
else if (ret == WAIT_PROC_EXITED)
|
|
||||||
; /* For POSIX locks, the process holding the lock has exited. */
|
|
||||||
else if (ret == WAIT_SIGNAL_ARRIVED)
|
|
||||||
{
|
{
|
||||||
/* A signal came in. */
|
/* A signal came in. */
|
||||||
if (!_my_tls.call_signal_handler ())
|
lock->lf_next = *clean;
|
||||||
return EINTR;
|
*clean = lock;
|
||||||
|
return EINTR;
|
||||||
}
|
}
|
||||||
else if (ret == WAIT_THREAD_CANCELED)
|
else if (ret == WAIT_THREAD_CANCELED)
|
||||||
{
|
{
|
||||||
/* The thread has been sent a cancellation request. */
|
/* The thread has been sent a cancellation request. */
|
||||||
pthread::static_cancel_self ();
|
lock->lf_next = *clean;
|
||||||
|
*clean = lock;
|
||||||
|
return ECANCELED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
/* The lock object has been set to signalled or ...
|
||||||
system_printf ("Shouldn't happen! ret = %lu, error: %lu\n",
|
for POSIX locks, the process holding the lock has exited, or ...
|
||||||
ret, GetLastError ());
|
Just a timeout. Just retry. */
|
||||||
return geterrno_from_win_error ();
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
allow_others_to_sync ();
|
allow_others_to_sync ();
|
||||||
/*
|
/*
|
||||||
|
@ -1268,7 +1302,7 @@ lf_getlock (lockf_t *lock, inode_t *node, struct __flock64 *fl)
|
||||||
if ((block = lf_getblock (lock, node)))
|
if ((block = lf_getblock (lock, node)))
|
||||||
{
|
{
|
||||||
if (block->lf_obj)
|
if (block->lf_obj)
|
||||||
NtClose (block->lf_obj);
|
block->close_lock_obj ();
|
||||||
fl->l_type = block->lf_type;
|
fl->l_type = block->lf_type;
|
||||||
fl->l_whence = SEEK_SET;
|
fl->l_whence = SEEK_SET;
|
||||||
fl->l_start = block->lf_start;
|
fl->l_start = block->lf_start;
|
||||||
|
@ -1296,8 +1330,6 @@ lf_getblock (lockf_t *lock, inode_t *node)
|
||||||
lockf_t **prev, *overlap;
|
lockf_t **prev, *overlap;
|
||||||
lockf_t *lf = node->get_all_locks_list ();
|
lockf_t *lf = node->get_all_locks_list ();
|
||||||
int ovcase;
|
int ovcase;
|
||||||
NTSTATUS status;
|
|
||||||
EVENT_BASIC_INFORMATION ebi;
|
|
||||||
|
|
||||||
prev = lock->lf_head;
|
prev = lock->lf_head;
|
||||||
while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap)))
|
while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap)))
|
||||||
|
@ -1308,17 +1340,18 @@ lf_getblock (lockf_t *lock, inode_t *node)
|
||||||
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
|
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
|
||||||
{
|
{
|
||||||
/* Open the event object for synchronization. */
|
/* Open the event object for synchronization. */
|
||||||
if (!overlap->open_lock_obj () || (overlap->lf_flags & F_POSIX))
|
if (overlap->open_lock_obj ())
|
||||||
return overlap;
|
{
|
||||||
/* In case of BSD flock locks, check if the event object is
|
/* If we found a POSIX lock, it will block us. */
|
||||||
signalled. If so, the overlap doesn't actually exist anymore.
|
if (overlap->lf_flags & F_POSIX)
|
||||||
There are just a few open handles left. */
|
return overlap;
|
||||||
status = NtQueryEvent (overlap->lf_obj, EventBasicInformation,
|
/* In case of BSD flock locks, check if the event object is
|
||||||
&ebi, sizeof ebi, NULL);
|
signalled. If so, the overlap doesn't actually exist anymore.
|
||||||
if (!NT_SUCCESS (status) || ebi.SignalState == 0)
|
There are just a few open handles left. */
|
||||||
return overlap;
|
if (!IsEventSignalled (overlap->lf_obj))
|
||||||
NtClose (overlap->lf_obj);
|
return overlap;
|
||||||
overlap->lf_obj = NULL;
|
overlap->close_lock_obj ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Nope, point to the next one on the list and
|
* Nope, point to the next one on the list and
|
||||||
|
|
|
@ -15,13 +15,16 @@
|
||||||
#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000)
|
#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000)
|
||||||
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
|
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
|
||||||
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
|
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
|
||||||
#ifndef STATUS_INVALID_INFO_CLASS
|
#ifdef STATUS_INVALID_INFO_CLASS /* Defined as unsigned value in subauth.h */
|
||||||
/* Some w32api header file defines this so we need to conditionalize this
|
#undef STATUS_INVALID_INFO_CLASS
|
||||||
define to avoid warnings. */
|
|
||||||
#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
|
|
||||||
#endif
|
#endif
|
||||||
|
#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
|
||||||
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xc0000002)
|
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xc0000002)
|
||||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
|
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
|
||||||
|
#ifdef STATUS_INVALID_HANDLE /* Defined as unsigned value in winbase.h */
|
||||||
|
#undef STATUS_INVALID_HANDLE
|
||||||
|
#endif
|
||||||
|
#define STATUS_INVALID_HANDLE ((NTSTATUS) 0xc0000008)
|
||||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
|
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
|
||||||
#define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f)
|
#define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xc000000f)
|
||||||
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
|
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
|
||||||
|
@ -32,6 +35,7 @@
|
||||||
#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xc0000024)
|
#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xc0000024)
|
||||||
#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xc0000033)
|
#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xc0000033)
|
||||||
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
|
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
|
||||||
|
#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xc0000035)
|
||||||
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
|
#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
|
||||||
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
|
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
|
||||||
#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xc000004f)
|
#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xc000004f)
|
||||||
|
@ -1210,6 +1214,7 @@ extern "C"
|
||||||
PULONG);
|
PULONG);
|
||||||
NTSTATUS NTAPI NtRollbackTransaction (HANDLE, BOOLEAN);
|
NTSTATUS NTAPI NtRollbackTransaction (HANDLE, BOOLEAN);
|
||||||
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
|
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
|
||||||
|
NTSTATUS NTAPI NtSetEvent (HANDLE, PULONG);
|
||||||
NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||||
FILE_INFORMATION_CLASS);
|
FILE_INFORMATION_CLASS);
|
||||||
NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREAD_INFORMATION_CLASS,
|
NTSTATUS NTAPI NtSetInformationThread (HANDLE, THREAD_INFORMATION_CLASS,
|
||||||
|
|
Loading…
Reference in New Issue