* flock.cc (LOCK_DIR_NAME_FMT): Define.
(LOCK_DIR_NAME_LEN): Define. (LOCK_DIR_NAME_DEV_OFF): Define. (LOCK_DIR_NAME_INO_OFF): Define. (LOCK_OBJ_NAME_FMT): Define. Add comment. (class lockf_t): Use bitsize-explicit types. Declare from_obj_name, (class inode_t): Make use, unuse and inuse methods public. Add a lock argument to get method declaration. (inode_t::get): Add lock argument. Only lock node if lock arg is true. (inode_t::inode_t): Use LOCK_DIR_NAME_FMT as format string. (lockf_t::from_obj_name): New method to generate lockf_t content from lock event object basename. (inode_t::get_all_locks_list): Just call from_obj_name here and copy result into final lockf_t. (create_lock_obj_attr): Use LOCK_OBJ_NAME_FMT as format string. (create_lock_in_parent): New thread function to create lockf_t structure in parent process. (delete_lock_in_parent): New thread function to reap stale BSD locks in parent process. (lockf_t::create_lock_obj): Try to duplicate lock object handle into parent process and call create_lock_in_parent as parent remote thread. (lockf_t::del_lock_obj): Call delete_lock_in_parent as parent remote thread. (fhandler_disk_file::lock): Add lock arg to inode_t::get call.
This commit is contained in:
parent
3a90360cf0
commit
dbf576fd86
@ -1,3 +1,30 @@
|
|||||||
|
2012-02-26 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* flock.cc (LOCK_DIR_NAME_FMT): Define.
|
||||||
|
(LOCK_DIR_NAME_LEN): Define.
|
||||||
|
(LOCK_DIR_NAME_DEV_OFF): Define.
|
||||||
|
(LOCK_DIR_NAME_INO_OFF): Define.
|
||||||
|
(LOCK_OBJ_NAME_FMT): Define. Add comment.
|
||||||
|
(class lockf_t): Use bitsize-explicit types. Declare from_obj_name,
|
||||||
|
(class inode_t): Make use, unuse and inuse methods public. Add a
|
||||||
|
lock argument to get method declaration.
|
||||||
|
(inode_t::get): Add lock argument. Only lock node if lock arg is true.
|
||||||
|
(inode_t::inode_t): Use LOCK_DIR_NAME_FMT as format string.
|
||||||
|
(lockf_t::from_obj_name): New method to generate lockf_t content from
|
||||||
|
lock event object basename.
|
||||||
|
(inode_t::get_all_locks_list): Just call from_obj_name here and copy
|
||||||
|
result into final lockf_t.
|
||||||
|
(create_lock_obj_attr): Use LOCK_OBJ_NAME_FMT as format string.
|
||||||
|
(create_lock_in_parent): New thread function to create lockf_t
|
||||||
|
structure in parent process.
|
||||||
|
(delete_lock_in_parent): New thread function to reap stale BSD locks in
|
||||||
|
parent process.
|
||||||
|
(lockf_t::create_lock_obj): Try to duplicate lock object handle into
|
||||||
|
parent process and call create_lock_in_parent as parent remote thread.
|
||||||
|
(lockf_t::del_lock_obj): Call delete_lock_in_parent as parent remote
|
||||||
|
thread.
|
||||||
|
(fhandler_disk_file::lock): Add lock arg to inode_t::get call.
|
||||||
|
|
||||||
2012-02-25 Christopher Faylor <me.cygwin2012@cgf.cx>
|
2012-02-25 Christopher Faylor <me.cygwin2012@cgf.cx>
|
||||||
|
|
||||||
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 12.
|
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 12.
|
||||||
|
@ -124,7 +124,14 @@ static NO_COPY muto lockf_guard;
|
|||||||
#define INODE_LIST_LOCK() (lockf_guard.init ("lockf_guard")->acquire ())
|
#define INODE_LIST_LOCK() (lockf_guard.init ("lockf_guard")->acquire ())
|
||||||
#define INODE_LIST_UNLOCK() (lockf_guard.release ())
|
#define INODE_LIST_UNLOCK() (lockf_guard.release ())
|
||||||
|
|
||||||
#define LOCK_OBJ_NAME_LEN 69
|
#define LOCK_DIR_NAME_FMT L"flock-%08x-%016X"
|
||||||
|
#define LOCK_DIR_NAME_LEN 31 /* Length of the resulting name */
|
||||||
|
#define LOCK_DIR_NAME_DEV_OFF 6 /* Offset to device number */
|
||||||
|
#define LOCK_DIR_NAME_INO_OFF 15 /* Offset to inode number */
|
||||||
|
|
||||||
|
/* Don't change format without also changing lockf_t::from_obj_name! */
|
||||||
|
#define LOCK_OBJ_NAME_FMT L"%02x-%01x-%016X-%016X-%016X-%08x-%04x"
|
||||||
|
#define LOCK_OBJ_NAME_LEN 69 /* Length of the resulting name */
|
||||||
|
|
||||||
#define FLOCK_INODE_DIR_ACCESS (DIRECTORY_QUERY \
|
#define FLOCK_INODE_DIR_ACCESS (DIRECTORY_QUERY \
|
||||||
| DIRECTORY_TRAVERSE \
|
| DIRECTORY_TRAVERSE \
|
||||||
@ -225,11 +232,11 @@ struct lockfattr_t
|
|||||||
class lockf_t
|
class lockf_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
|
uint16_t lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
|
||||||
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
uint16_t 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
|
int64_t 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 */
|
||||||
uint16_t lf_ver; /* Version number of the lock. If a released
|
uint16_t lf_ver; /* Version number of the lock. If a released
|
||||||
@ -255,6 +262,9 @@ class lockf_t
|
|||||||
{}
|
{}
|
||||||
~lockf_t ();
|
~lockf_t ();
|
||||||
|
|
||||||
|
bool from_obj_name (class inode_t *node, class lockf_t **head,
|
||||||
|
const wchar_t *name);
|
||||||
|
|
||||||
/* Used to create all locks list in a given TLS buffer. */
|
/* Used to create all locks list in a given TLS buffer. */
|
||||||
void *operator new (size_t size, void *p)
|
void *operator new (size_t size, void *p)
|
||||||
{ return p; }
|
{ return p; }
|
||||||
@ -292,10 +302,6 @@ class inode_t
|
|||||||
HANDLE i_mtx;
|
HANDLE i_mtx;
|
||||||
uint32_t i_cnt; /* # of threads referencing this instance. */
|
uint32_t i_cnt; /* # of threads referencing this instance. */
|
||||||
|
|
||||||
void use () { ++i_cnt; }
|
|
||||||
void unuse () { if (i_cnt > 0) --i_cnt; }
|
|
||||||
bool inuse () { return i_cnt > 0; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inode_t (__dev32_t dev, __ino64_t ino);
|
inode_t (__dev32_t dev, __ino64_t ino);
|
||||||
~inode_t ();
|
~inode_t ();
|
||||||
@ -305,11 +311,15 @@ class inode_t
|
|||||||
void operator delete (void *p)
|
void operator delete (void *p)
|
||||||
{ cfree (p); }
|
{ cfree (p); }
|
||||||
|
|
||||||
static inode_t *get (__dev32_t dev, __ino64_t ino, bool create_if_missing);
|
static inode_t *get (__dev32_t dev, __ino64_t ino,
|
||||||
|
bool create_if_missing, bool lock);
|
||||||
|
|
||||||
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
|
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
|
||||||
void UNLOCK () { ReleaseMutex (i_mtx); }
|
void UNLOCK () { ReleaseMutex (i_mtx); }
|
||||||
|
|
||||||
|
void use () { ++i_cnt; }
|
||||||
|
void unuse () { if (i_cnt > 0) --i_cnt; }
|
||||||
|
bool inuse () { return i_cnt > 0; }
|
||||||
void notused () { i_cnt = 0; }
|
void notused () { i_cnt = 0; }
|
||||||
|
|
||||||
void unlock_and_remove_if_unused ();
|
void unlock_and_remove_if_unused ();
|
||||||
@ -390,7 +400,7 @@ inode_t::del_my_locks (long long id, HANDLE fhdl)
|
|||||||
void
|
void
|
||||||
fhandler_base::del_my_locks (del_lock_called_from from)
|
fhandler_base::del_my_locks (del_lock_called_from from)
|
||||||
{
|
{
|
||||||
inode_t *node = inode_t::get (get_dev (), get_ino (), false);
|
inode_t *node = inode_t::get (get_dev (), get_ino (), false, true);
|
||||||
if (node)
|
if (node)
|
||||||
{
|
{
|
||||||
/* When we're called from fixup_after_exec, the fhandler is a
|
/* When we're called from fixup_after_exec, the fhandler is a
|
||||||
@ -458,7 +468,7 @@ fixup_lockf_after_exec ()
|
|||||||
file. The file is specified by the device and inode_t number. If inode_t
|
file. The file is specified by the device and inode_t number. If inode_t
|
||||||
doesn't exist, create it. */
|
doesn't exist, create it. */
|
||||||
inode_t *
|
inode_t *
|
||||||
inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing)
|
inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing, bool lock)
|
||||||
{
|
{
|
||||||
inode_t *node;
|
inode_t *node;
|
||||||
|
|
||||||
@ -475,7 +485,7 @@ inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing)
|
|||||||
if (node)
|
if (node)
|
||||||
node->use ();
|
node->use ();
|
||||||
INODE_LIST_UNLOCK ();
|
INODE_LIST_UNLOCK ();
|
||||||
if (node)
|
if (node && lock)
|
||||||
node->LOCK ();
|
node->LOCK ();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -492,7 +502,7 @@ inode_t::inode_t (__dev32_t dev, __ino64_t ino)
|
|||||||
parent_dir = get_shared_parent_dir ();
|
parent_dir = get_shared_parent_dir ();
|
||||||
/* Create a subdir which is named after the device and inode_t numbers
|
/* Create a subdir which is named after the device and inode_t numbers
|
||||||
of the given file, in hex notation. */
|
of the given file, in hex notation. */
|
||||||
int len = __small_swprintf (name, L"flock-%08x-%016X", dev, ino);
|
int len = __small_swprintf (name, LOCK_DIR_NAME_FMT, dev, ino);
|
||||||
RtlInitCountedUnicodeString (&uname, name, len * sizeof (WCHAR));
|
RtlInitCountedUnicodeString (&uname, name, len * sizeof (WCHAR));
|
||||||
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
|
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
|
||||||
parent_dir, everyone_sd (FLOCK_INODE_DIR_ACCESS));
|
parent_dir, everyone_sd (FLOCK_INODE_DIR_ACCESS));
|
||||||
@ -516,6 +526,45 @@ inode_t::inode_t (__dev32_t dev, __ino64_t ino)
|
|||||||
#define MAX_LOCKF_CNT ((intptr_t)((NT_MAX_PATH * sizeof (WCHAR)) \
|
#define MAX_LOCKF_CNT ((intptr_t)((NT_MAX_PATH * sizeof (WCHAR)) \
|
||||||
/ sizeof (lockf_t)))
|
/ sizeof (lockf_t)))
|
||||||
|
|
||||||
|
bool
|
||||||
|
lockf_t::from_obj_name (inode_t *node, lockf_t **head, const wchar_t *name)
|
||||||
|
{
|
||||||
|
wchar_t *endptr;
|
||||||
|
|
||||||
|
/* "%02x-%01x-%016X-%016X-%016X-%08x-%04x",
|
||||||
|
lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid, lf_ver */
|
||||||
|
lf_flags = wcstol (name, &endptr, 16);
|
||||||
|
if ((lf_flags & ~(F_FLOCK | F_POSIX)) != 0
|
||||||
|
|| ((lf_flags & (F_FLOCK | F_POSIX)) == (F_FLOCK | F_POSIX)))
|
||||||
|
return false;
|
||||||
|
lf_type = wcstol (endptr + 1, &endptr, 16);
|
||||||
|
if ((lf_type != F_RDLCK && lf_type != F_WRLCK) || !endptr || *endptr != L'-')
|
||||||
|
return false;
|
||||||
|
lf_start = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
||||||
|
if (lf_start < 0 || !endptr || *endptr != L'-')
|
||||||
|
return false;
|
||||||
|
lf_end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
||||||
|
if (lf_end < -1LL
|
||||||
|
|| (lf_end > 0 && lf_end < lf_start)
|
||||||
|
|| !endptr || *endptr != L'-')
|
||||||
|
return false;
|
||||||
|
lf_id = wcstoll (endptr + 1, &endptr, 16);
|
||||||
|
if (!endptr || *endptr != L'-'
|
||||||
|
|| ((lf_flags & F_POSIX) && (lf_id < 1 || lf_id > ULONG_MAX)))
|
||||||
|
return false;
|
||||||
|
lf_wid = wcstoul (endptr + 1, &endptr, 16);
|
||||||
|
if (!endptr || *endptr != L'-')
|
||||||
|
return false;
|
||||||
|
lf_ver = wcstoul (endptr + 1, &endptr, 16);
|
||||||
|
if (endptr && *endptr != L'\0')
|
||||||
|
return false;
|
||||||
|
lf_head = head;
|
||||||
|
lf_inode = node;
|
||||||
|
lf_next = NULL;
|
||||||
|
lf_obj = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
lockf_t *
|
lockf_t *
|
||||||
inode_t::get_all_locks_list ()
|
inode_t::get_all_locks_list ()
|
||||||
{
|
{
|
||||||
@ -526,7 +575,7 @@ inode_t::get_all_locks_list ()
|
|||||||
} f;
|
} f;
|
||||||
ULONG context;
|
ULONG context;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
lockf_t *lock = i_all_lf;
|
lockf_t newlock, *lock = i_all_lf;
|
||||||
|
|
||||||
for (BOOLEAN restart = TRUE;
|
for (BOOLEAN restart = TRUE;
|
||||||
NT_SUCCESS (status = NtQueryDirectoryObject (i_dir, &f, sizeof f, TRUE,
|
NT_SUCCESS (status = NtQueryDirectoryObject (i_dir, &f, sizeof f, TRUE,
|
||||||
@ -535,32 +584,8 @@ inode_t::get_all_locks_list ()
|
|||||||
{
|
{
|
||||||
if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
|
if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
|
||||||
continue;
|
continue;
|
||||||
wchar_t *wc = f.dbi.ObjectName.Buffer, *endptr;
|
f.dbi.ObjectName.Buffer[LOCK_OBJ_NAME_LEN] = L'\0';
|
||||||
/* "%02x-%01x-%016X-%016X-%016X-%08x-%04x",
|
if (!newlock.from_obj_name (this, &i_all_lf, f.dbi.ObjectName.Buffer))
|
||||||
lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid, lf_ver */
|
|
||||||
wc[LOCK_OBJ_NAME_LEN] = L'\0';
|
|
||||||
short flags = wcstol (wc, &endptr, 16);
|
|
||||||
if ((flags & ~(F_FLOCK | F_POSIX)) != 0
|
|
||||||
|| ((flags & (F_FLOCK | F_POSIX)) == (F_FLOCK | F_POSIX)))
|
|
||||||
continue;
|
|
||||||
short type = wcstol (endptr + 1, &endptr, 16);
|
|
||||||
if ((type != F_RDLCK && type != F_WRLCK) || !endptr || *endptr != L'-')
|
|
||||||
continue;
|
|
||||||
_off64_t start = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
|
||||||
if (start < 0 || !endptr || *endptr != L'-')
|
|
||||||
continue;
|
|
||||||
_off64_t end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
|
||||||
if (end < -1LL || (end > 0 && end < start) || !endptr || *endptr != L'-')
|
|
||||||
continue;
|
|
||||||
long long id = wcstoll (endptr + 1, &endptr, 16);
|
|
||||||
if (!endptr || *endptr != L'-'
|
|
||||||
|| ((flags & F_POSIX) && (id < 1 || id > ULONG_MAX)))
|
|
||||||
continue;
|
|
||||||
DWORD wid = wcstoul (endptr + 1, &endptr, 16);
|
|
||||||
if (!endptr || *endptr != L'-')
|
|
||||||
continue;
|
|
||||||
uint16_t ver = wcstoul (endptr + 1, &endptr, 16);
|
|
||||||
if (endptr && *endptr != L'\0')
|
|
||||||
continue;
|
continue;
|
||||||
if (lock - i_all_lf >= MAX_LOCKF_CNT)
|
if (lock - i_all_lf >= MAX_LOCKF_CNT)
|
||||||
{
|
{
|
||||||
@ -570,8 +595,7 @@ inode_t::get_all_locks_list ()
|
|||||||
}
|
}
|
||||||
if (lock > i_all_lf)
|
if (lock > i_all_lf)
|
||||||
lock[-1].lf_next = lock;
|
lock[-1].lf_next = lock;
|
||||||
new (lock++) lockf_t (this, &i_all_lf,
|
new (lock++) lockf_t (newlock);
|
||||||
flags, type, start, end, id, wid, ver);
|
|
||||||
}
|
}
|
||||||
/* If no lock has been found, return NULL. */
|
/* If no lock has been found, return NULL. */
|
||||||
if (lock == i_all_lf)
|
if (lock == i_all_lf)
|
||||||
@ -584,7 +608,7 @@ inode_t::get_all_locks_list ()
|
|||||||
POBJECT_ATTRIBUTES
|
POBJECT_ATTRIBUTES
|
||||||
lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
|
lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
|
||||||
{
|
{
|
||||||
__small_swprintf (attr->name, L"%02x-%01x-%016X-%016X-%016X-%08x-%04x",
|
__small_swprintf (attr->name, LOCK_OBJ_NAME_FMT,
|
||||||
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, lf_end,
|
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, lf_end,
|
||||||
lf_id, lf_wid, lf_ver);
|
lf_id, lf_wid, lf_ver);
|
||||||
RtlInitCountedUnicodeString (&attr->uname, attr->name,
|
RtlInitCountedUnicodeString (&attr->uname, attr->name,
|
||||||
@ -594,6 +618,111 @@ lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
|
|||||||
return &attr->attr;
|
return &attr->attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI
|
||||||
|
create_lock_in_parent (PVOID param)
|
||||||
|
{
|
||||||
|
HANDLE lf_obj;
|
||||||
|
ULONG size;
|
||||||
|
OBJECT_NAME_INFORMATION *ntfn;
|
||||||
|
NTSTATUS status;
|
||||||
|
wchar_t *lockname, *inodename, *endptr;
|
||||||
|
__dev32_t dev;
|
||||||
|
__ino64_t ino;
|
||||||
|
inode_t *node;
|
||||||
|
lockf_t newlock, *lock;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
/* param is the handle to the lock object, created by caller. */
|
||||||
|
lf_obj = (HANDLE) param;
|
||||||
|
/* Fetch object path from handle. Typically the length of the path
|
||||||
|
is 146 characters, starting with
|
||||||
|
"\BaseNamedObject\cygwin-1S5-<16-hex-digits>\..." */
|
||||||
|
size = sizeof (OBJECT_NAME_INFORMATION) + 256 * sizeof (WCHAR);
|
||||||
|
ntfn = (OBJECT_NAME_INFORMATION *) alloca (size);
|
||||||
|
memset (ntfn, 0, size);
|
||||||
|
status = NtQueryObject (lf_obj, ObjectNameInformation, ntfn, size, &size);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
goto err;
|
||||||
|
ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
|
||||||
|
/* Sanity check so that we don't peek into unchartered territory. */
|
||||||
|
if (ntfn->Name.Length < LOCK_OBJ_NAME_LEN + LOCK_DIR_NAME_LEN + 1)
|
||||||
|
goto err;
|
||||||
|
/* The names have fixed size, so we know where the substrings start. */
|
||||||
|
lockname = ntfn->Name.Buffer + ntfn->Name.Length / sizeof (WCHAR)
|
||||||
|
- LOCK_OBJ_NAME_LEN;
|
||||||
|
inodename = lockname - LOCK_DIR_NAME_LEN - 1;
|
||||||
|
dev = wcstoul (inodename + LOCK_DIR_NAME_DEV_OFF, &endptr, 16);
|
||||||
|
if (*endptr != L'-')
|
||||||
|
goto err;
|
||||||
|
ino = wcstoull (inodename + LOCK_DIR_NAME_INO_OFF, &endptr, 16);
|
||||||
|
if (*endptr != L'\\')
|
||||||
|
goto err;
|
||||||
|
if (!newlock.from_obj_name (NULL, NULL, lockname))
|
||||||
|
goto err;
|
||||||
|
/* Check if we have an open file handle with the same unique id. */
|
||||||
|
{
|
||||||
|
cnt = 0;
|
||||||
|
cygheap_fdenum cfd (true);
|
||||||
|
while (cfd.next () >= 0)
|
||||||
|
if (cfd->get_unique_id () == newlock.lf_id && ++cnt > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* If not, close handle and return. */
|
||||||
|
if (!cnt)
|
||||||
|
{
|
||||||
|
NtClose (lf_obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* otherwise generate inode from directory name... */
|
||||||
|
node = inode_t::get (dev, ino, true, false);
|
||||||
|
/* ...and generate lock from object name. */
|
||||||
|
lock = new lockf_t (newlock);
|
||||||
|
lock->lf_inode = node;
|
||||||
|
lock->lf_head = &node->i_lockf;
|
||||||
|
lock->lf_next = node->i_lockf;
|
||||||
|
lock->lf_obj = lf_obj;
|
||||||
|
node->i_lockf = lock;
|
||||||
|
node->unuse ();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
system_printf ("Adding <%S> lock failed", &ntfn->Name);
|
||||||
|
NtClose (lf_obj);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI
|
||||||
|
delete_lock_in_parent (PVOID param)
|
||||||
|
{
|
||||||
|
inode_t *node;
|
||||||
|
lockf_t *lock, **prev;
|
||||||
|
|
||||||
|
/* Scan list of all inodes, and reap stale BSD lock if lf_id matches.
|
||||||
|
Remove inode if empty. */
|
||||||
|
INODE_LIST_LOCK ();
|
||||||
|
LIST_FOREACH (node, &cygheap->inode_list, i_next)
|
||||||
|
if (!node->inuse ())
|
||||||
|
{
|
||||||
|
for (prev = &node->i_lockf, lock = *prev; lock; lock = *prev)
|
||||||
|
{
|
||||||
|
if ((lock->lf_flags & F_FLOCK) && IsEventSignalled (lock->lf_obj))
|
||||||
|
{
|
||||||
|
*prev = lock->lf_next;
|
||||||
|
delete lock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev = &lock->lf_next;
|
||||||
|
}
|
||||||
|
if (node->i_lockf == NULL)
|
||||||
|
{
|
||||||
|
LIST_REMOVE (node, i_next);
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INODE_LIST_UNLOCK ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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. */
|
namespace. */
|
||||||
void
|
void
|
||||||
@ -629,6 +758,54 @@ lockf_t::create_lock_obj ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!NT_SUCCESS (status));
|
while (!NT_SUCCESS (status));
|
||||||
|
/* For BSD locks, notify the parent process. */
|
||||||
|
if (lf_flags & F_FLOCK)
|
||||||
|
{
|
||||||
|
HANDLE parent_proc, parent_thread, parent_lf_obj;
|
||||||
|
|
||||||
|
pinfo p (myself->ppid);
|
||||||
|
if (!p) /* No access or not a Cygwin parent. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent_proc = OpenProcess (PROCESS_DUP_HANDLE
|
||||||
|
| PROCESS_CREATE_THREAD
|
||||||
|
| PROCESS_QUERY_INFORMATION
|
||||||
|
| PROCESS_VM_OPERATION
|
||||||
|
| PROCESS_VM_WRITE
|
||||||
|
| PROCESS_VM_READ,
|
||||||
|
FALSE, p->dwProcessId);
|
||||||
|
if (!parent_proc)
|
||||||
|
{
|
||||||
|
debug_printf ("OpenProcess (%u): %E", p->dwProcessId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), lf_obj, parent_proc,
|
||||||
|
&parent_lf_obj, TRUE, 0, DUPLICATE_SAME_ACCESS))
|
||||||
|
debug_printf ("DuplicateHandle (lf_obj): %E");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent_thread = CreateRemoteThread (parent_proc, NULL, 256 * 1024,
|
||||||
|
create_lock_in_parent,
|
||||||
|
parent_lf_obj,
|
||||||
|
STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||||
|
NULL);
|
||||||
|
if (!parent_thread)
|
||||||
|
{
|
||||||
|
debug_printf ("CreateRemoteThread: %E");
|
||||||
|
/* If thread didn't get started, close object handle in parent,
|
||||||
|
otherwise suffer handle leaks. */
|
||||||
|
DuplicateHandle (parent_proc, parent_lf_obj, parent_proc,
|
||||||
|
NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Must wait to avoid race conditions. */
|
||||||
|
WaitForSingleObject (parent_thread, INFINITE);
|
||||||
|
CloseHandle (parent_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle (parent_proc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
||||||
@ -665,7 +842,36 @@ 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))
|
||||||
NtSetEvent (lf_obj, NULL);
|
{
|
||||||
|
NtSetEvent (lf_obj, NULL);
|
||||||
|
/* For BSD locks, notify the parent process. */
|
||||||
|
if (lf_flags & F_FLOCK)
|
||||||
|
{
|
||||||
|
HANDLE parent_proc, parent_thread;
|
||||||
|
|
||||||
|
pinfo p (myself->ppid);
|
||||||
|
if (p && (parent_proc = OpenProcess (PROCESS_CREATE_THREAD
|
||||||
|
| PROCESS_QUERY_INFORMATION
|
||||||
|
| PROCESS_VM_OPERATION
|
||||||
|
| PROCESS_VM_WRITE
|
||||||
|
| PROCESS_VM_READ,
|
||||||
|
FALSE, p->dwProcessId)))
|
||||||
|
{
|
||||||
|
parent_thread = CreateRemoteThread (parent_proc, NULL,
|
||||||
|
256 * 1024, delete_lock_in_parent,
|
||||||
|
NULL,
|
||||||
|
STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||||
|
NULL);
|
||||||
|
if (parent_thread)
|
||||||
|
{
|
||||||
|
/* Must wait to avoid race conditions. */
|
||||||
|
WaitForSingleObject (parent_thread, INFINITE);
|
||||||
|
CloseHandle (parent_thread);
|
||||||
|
}
|
||||||
|
CloseHandle (parent_proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
close_lock_obj ();
|
close_lock_obj ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -815,7 +1021,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
|||||||
|
|
||||||
restart: /* Entry point after a restartable signal came in. */
|
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, true);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
set_errno (ENOLCK);
|
set_errno (ENOLCK);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user