w32: Fix deadlock introduced by keybox_file_rename.

* g10/keyring.c (keyring_lock) [W32]: Flush the close cache before
locking.
* kbx/keybox-init.c (keybox_lock) [W32]: Close the file before
locking.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-01-14 20:45:33 +01:00
parent 3b1248e007
commit 663c5d129a
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 47 additions and 18 deletions

View File

@ -328,8 +328,20 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
if (!keyring_is_writable(kr))
continue;
if (kr->is_locked)
;
else if (dotlock_take (kr->lockhd, -1) ) {
continue;
#ifdef HAVE_W32_SYSTEM
/* Under Windows we need to CloseHandle the file before we
* try to lock it. This is because another process might
* have taken the lock and is using keybox_file_rename to
* rename the base file. How if our dotlock_take below is
* waiting for the lock but we have the base file still
* open, keybox_file_rename will never succeed as we are
* in a deadlock. */
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0,
(char*)kr->fname);
#endif /*HAVE_W32_SYSTEM*/
if (dotlock_take (kr->lockhd, -1) ) {
log_info ("can't lock '%s'\n", kr->fname );
rc = GPG_ERR_GENERAL;
}
@ -343,8 +355,9 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
if (!keyring_is_writable(kr))
continue;
if (!kr->is_locked)
;
else if (dotlock_release (kr->lockhd))
continue;
if (dotlock_release (kr->lockhd))
log_info ("can't unlock '%s'\n", kr->fname );
else
kr->is_locked = 0;

View File

@ -286,27 +286,43 @@ keybox_lock (KEYBOX_HANDLE hd, int yes)
if (yes) /* Take the lock. */
{
if (kb->is_locked)
;
else if (dotlock_take (kb->lockhd, -1))
if (!kb->is_locked)
{
err = gpg_error_from_syserror ();
log_info ("can't lock '%s'\n", kb->fname );
#ifdef HAVE_W32_SYSTEM
/* Under Windows we need to close the file before we try
* to lock it. This is because another process might have
* taken the lock and is using keybox_file_rename to
* rename the base file. How if our dotlock_take below is
* waiting for the lock but we have the base file still
* open, keybox_file_rename will never succeed as we are
* in a deadlock. */
if (hd->fp)
{
fclose (hd->fp);
hd->fp = NULL;
}
#endif /*HAVE_W32_SYSTEM*/
if (dotlock_take (kb->lockhd, -1))
{
err = gpg_error_from_syserror ();
log_info ("can't lock '%s'\n", kb->fname );
}
else
kb->is_locked = 1;
}
else
kb->is_locked = 1;
}
else /* Release the lock. */
{
if (!kb->is_locked)
;
else if (dotlock_release (kb->lockhd))
if (kb->is_locked)
{
err = gpg_error_from_syserror ();
log_info ("can't unlock '%s'\n", kb->fname );
if (dotlock_release (kb->lockhd))
{
err = gpg_error_from_syserror ();
log_info ("can't unlock '%s'\n", kb->fname );
}
else
kb->is_locked = 0;
}
else
kb->is_locked = 0;
}
return err;