mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-13 22:21:09 +02:00
Allow arbitrary timeouts with dotlock.
This commit is contained in:
parent
8a033fecfb
commit
567a31c2a0
@ -1,3 +1,8 @@
|
|||||||
|
2011-09-28 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* dotlock.c (dotlock_take, dotlock_take_unix, dotlock_take_w32):
|
||||||
|
Implement arbitrary timeout values.
|
||||||
|
|
||||||
2011-09-27 Werner Koch <wk@g10code.com>
|
2011-09-27 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* dotlock.c (dotlock_take_unix): Check only the link count and not
|
* dotlock.c (dotlock_take_unix): Check only the link count and not
|
||||||
|
119
common/dotlock.c
119
common/dotlock.c
@ -87,8 +87,10 @@
|
|||||||
|
|
||||||
This function will wait until the lock is acquired. If an
|
This function will wait until the lock is acquired. If an
|
||||||
unexpected error occurs if will return non-zero and set ERRNO. If
|
unexpected error occurs if will return non-zero and set ERRNO. If
|
||||||
you pass (0) instead of (-1) the function does not wait if the file
|
you pass (0) instead of (-1) the function does not wait in case the
|
||||||
is already locked but returns -1 and sets ERRNO to EACCES.
|
file is already locked but returns -1 and sets ERRNO to EACCES.
|
||||||
|
Any other positive value for the second parameter is considered a
|
||||||
|
timeout valuie in milliseconds.
|
||||||
|
|
||||||
To release the lock you call:
|
To release the lock you call:
|
||||||
|
|
||||||
@ -805,15 +807,20 @@ dotlock_destroy (dotlock_t h)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_POSIX_SYSTEM
|
#ifdef HAVE_POSIX_SYSTEM
|
||||||
/* Unix specific code of make_dotlock. Returns 0 on success, -1 on
|
/* Unix specific code of make_dotlock. Returns 0 on success and -1 on
|
||||||
error and 1 to try again. */
|
error. */
|
||||||
static int
|
static int
|
||||||
dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
|
dotlock_take_unix (dotlock_t h, long timeout)
|
||||||
{
|
{
|
||||||
int pid;
|
int wtime = 0;
|
||||||
|
int sumtime = 0;
|
||||||
|
int pid;
|
||||||
|
int lastpid = -1;
|
||||||
|
int ownerchanged;
|
||||||
const char *maybe_dead="";
|
const char *maybe_dead="";
|
||||||
int same_node;
|
int same_node;
|
||||||
|
|
||||||
|
again:
|
||||||
if (h->use_o_excl)
|
if (h->use_o_excl)
|
||||||
{
|
{
|
||||||
/* No hardlink support - use open(O_EXCL). */
|
/* No hardlink support - use open(O_EXCL). */
|
||||||
@ -889,7 +896,7 @@ dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
my_info_0 ("lockfile disappeared\n");
|
my_info_0 ("lockfile disappeared\n");
|
||||||
return 1; /* Try again. */
|
goto again;
|
||||||
}
|
}
|
||||||
else if ( pid == getpid() && same_node )
|
else if ( pid == getpid() && same_node )
|
||||||
{
|
{
|
||||||
@ -904,24 +911,49 @@ dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
|
|||||||
of the stale file tries to lock right at the same time as we. */
|
of the stale file tries to lock right at the same time as we. */
|
||||||
my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
|
my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
|
||||||
unlink (h->lockname);
|
unlink (h->lockname);
|
||||||
return 1; /* Try again. */
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( timeout == -1 )
|
if (lastpid == -1)
|
||||||
|
lastpid = pid;
|
||||||
|
ownerchanged = (pid != lastpid);
|
||||||
|
|
||||||
|
if (timeout)
|
||||||
{
|
{
|
||||||
/* Wait until lock has been released. */
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
|
/* Wait until lock has been released. We use increasing retry
|
||||||
pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
|
intervals of 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s
|
||||||
|
but reset it if the lock owner meanwhile changed. */
|
||||||
|
if (!wtime || ownerchanged)
|
||||||
|
wtime = 50;
|
||||||
|
else if (wtime < 800)
|
||||||
|
wtime *= 2;
|
||||||
|
else if (wtime == 800)
|
||||||
|
wtime = 2000;
|
||||||
|
else if (wtime < 8000)
|
||||||
|
wtime *= 2;
|
||||||
|
|
||||||
/* We can't use sleep, cause signals may be blocked. */
|
if (timeout > 0)
|
||||||
tv.tv_sec = 1 + *backoff;
|
{
|
||||||
tv.tv_usec = 0;
|
if (wtime > timeout)
|
||||||
|
wtime = timeout;
|
||||||
|
timeout -= wtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
sumtime += wtime;
|
||||||
|
if (sumtime >= 1500)
|
||||||
|
{
|
||||||
|
sumtime = 0;
|
||||||
|
my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
|
||||||
|
pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tv.tv_sec = wtime / 1000;
|
||||||
|
tv.tv_usec = (wtime % 1000) * 1000;
|
||||||
select (0, NULL, NULL, NULL, &tv);
|
select (0, NULL, NULL, NULL, &tv);
|
||||||
if ( *backoff < 10 )
|
goto again;
|
||||||
++*backoff;
|
|
||||||
return 1; /* Try again. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jnlib_set_errno (EACCES);
|
jnlib_set_errno (EACCES);
|
||||||
@ -931,14 +963,16 @@ dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
/* Windows specific code of make_dotlock. Returns 0 on success, -1 on
|
/* Windows specific code of make_dotlock. Returns 0 on success and -1 on
|
||||||
error and 1 to try again. */
|
error. */
|
||||||
static int
|
static int
|
||||||
dotlock_take_w32 (dotlock_t h, long timeout, int *backoff)
|
dotlock_take_w32 (dotlock_t h, long timeout)
|
||||||
{
|
{
|
||||||
|
int wtime = 0;
|
||||||
int w32err;
|
int w32err;
|
||||||
OVERLAPPED ovl;
|
OVERLAPPED ovl;
|
||||||
|
|
||||||
|
again:
|
||||||
/* Lock one byte at offset 0. The offset is given by OVL. */
|
/* Lock one byte at offset 0. The offset is given by OVL. */
|
||||||
memset (&ovl, 0, sizeof ovl);
|
memset (&ovl, 0, sizeof ovl);
|
||||||
if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
|
if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
|
||||||
@ -956,14 +990,31 @@ dotlock_take_w32 (dotlock_t h, long timeout, int *backoff)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( timeout == -1 )
|
if (timeout)
|
||||||
{
|
{
|
||||||
/* Wait until lock has been released. */
|
/* Wait until lock has been released. We use retry intervals of
|
||||||
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
|
50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s. */
|
||||||
Sleep ((1 + *backoff)*1000);
|
if (!wtime)
|
||||||
if ( *backoff < 10 )
|
wtime = 50;
|
||||||
++*backoff;
|
else if (wtime < 800)
|
||||||
return 1; /* Try again. */
|
wtime *= 2;
|
||||||
|
else if (wtime == 800)
|
||||||
|
wtime = 2000;
|
||||||
|
else if (wtime < 8000)
|
||||||
|
wtime *= 2;
|
||||||
|
|
||||||
|
if (timeout > 0)
|
||||||
|
{
|
||||||
|
if (wtime > timeout)
|
||||||
|
wtime = timeout;
|
||||||
|
timeout -= wtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wtime >= 800)
|
||||||
|
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
|
||||||
|
|
||||||
|
Sleep (wtime);
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -973,12 +1024,10 @@ dotlock_take_w32 (dotlock_t h, long timeout, int *backoff)
|
|||||||
|
|
||||||
/* Take a lock on H. A value of 0 for TIMEOUT returns immediately if
|
/* Take a lock on H. A value of 0 for TIMEOUT returns immediately if
|
||||||
the lock can't be taked, -1 waits forever (hopefully not), other
|
the lock can't be taked, -1 waits forever (hopefully not), other
|
||||||
values are reserved (planned to be timeouts in milliseconds).
|
values wait for TIMEOUT milliseconds. Returns: 0 on success */
|
||||||
Returns: 0 on success */
|
|
||||||
int
|
int
|
||||||
dotlock_take (dotlock_t h, long timeout)
|
dotlock_take (dotlock_t h, long timeout)
|
||||||
{
|
{
|
||||||
int backoff = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ( h->disable )
|
if ( h->disable )
|
||||||
@ -990,15 +1039,11 @@ dotlock_take (dotlock_t h, long timeout)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
ret = dotlock_take_w32 (h, timeout, &backoff);
|
ret = dotlock_take_w32 (h, timeout);
|
||||||
#else /*!HAVE_DOSISH_SYSTEM*/
|
#else /*!HAVE_DOSISH_SYSTEM*/
|
||||||
ret = dotlock_take_unix (h, timeout, &backoff);
|
ret = dotlock_take_unix (h, timeout);
|
||||||
#endif /*!HAVE_DOSISH_SYSTEM*/
|
#endif /*!HAVE_DOSISH_SYSTEM*/
|
||||||
}
|
|
||||||
while (ret == 1);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user