mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-11 21:48:50 +01:00
common: Fix a race condition removing stale lockfile.
* common/dotlock.c (read_lockfile): Return the file descriptor when R_FD is available. (dotlock_take_unix): Check the case the lockfile was already removed. -- GnuPG-bug-id: 5884 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
a30359cecb
commit
d94b411f12
@ -526,7 +526,7 @@ maybe_deadlock (dotlock_t h)
|
|||||||
has been created on the same node. */
|
has been created on the same node. */
|
||||||
#ifdef HAVE_POSIX_SYSTEM
|
#ifdef HAVE_POSIX_SYSTEM
|
||||||
static int
|
static int
|
||||||
read_lockfile (dotlock_t h, int *same_node )
|
read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|
||||||
{
|
{
|
||||||
char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
|
char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
|
||||||
names are usually shorter. */
|
names are usually shorter. */
|
||||||
@ -579,7 +579,11 @@ read_lockfile (dotlock_t h, int *same_node )
|
|||||||
nread += res;
|
nread += res;
|
||||||
}
|
}
|
||||||
while (res && nread != expected_len);
|
while (res && nread != expected_len);
|
||||||
close(fd);
|
|
||||||
|
if (r_fd)
|
||||||
|
*r_fd = fd;
|
||||||
|
else
|
||||||
|
close(fd);
|
||||||
|
|
||||||
if (nread < 11)
|
if (nread < 11)
|
||||||
{
|
{
|
||||||
@ -1027,13 +1031,12 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
const char *maybe_dead="";
|
const char *maybe_dead="";
|
||||||
int same_node;
|
int same_node;
|
||||||
int saveerrno;
|
int saveerrno;
|
||||||
|
int fd;
|
||||||
|
|
||||||
again:
|
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). */
|
||||||
int fd;
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
my_set_errno (0);
|
my_set_errno (0);
|
||||||
@ -1103,7 +1106,7 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for stale lock files. */
|
/* Check for stale lock files. */
|
||||||
if ( (pid = read_lockfile (h, &same_node)) == -1 )
|
if ( (pid = read_lockfile (h, &same_node, &fd)) == -1 )
|
||||||
{
|
{
|
||||||
if ( errno != ENOENT )
|
if ( errno != ENOENT )
|
||||||
{
|
{
|
||||||
@ -1119,18 +1122,30 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
{
|
{
|
||||||
my_info_0 ("Oops: lock already held by us\n");
|
my_info_0 ("Oops: lock already held by us\n");
|
||||||
h->locked = 1;
|
h->locked = 1;
|
||||||
|
|
||||||
|
close (fd);
|
||||||
return 0; /* okay */
|
return 0; /* okay */
|
||||||
}
|
}
|
||||||
else if ( same_node && kill (pid, 0) && errno == ESRCH )
|
else if ( same_node && kill (pid, 0) && errno == ESRCH )
|
||||||
{
|
{
|
||||||
/* Note: It is unlikely that we get a race here unless a pid is
|
struct stat sb;
|
||||||
reused too fast or a new process with the same pid as the one
|
|
||||||
of the stale file tries to lock right at the same time as we. */
|
/* Check if it's unlocked during examining the lockfile. */
|
||||||
|
if (fstat (fd, &sb) || sb.st_nlink == 0)
|
||||||
|
{
|
||||||
|
/* It's gone already. */
|
||||||
|
close (fd);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
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);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
if (lastpid == -1)
|
if (lastpid == -1)
|
||||||
lastpid = pid;
|
lastpid = pid;
|
||||||
ownerchanged = (pid != lastpid);
|
ownerchanged = (pid != lastpid);
|
||||||
@ -1277,7 +1292,7 @@ dotlock_release_unix (dotlock_t h)
|
|||||||
int pid, same_node;
|
int pid, same_node;
|
||||||
int saveerrno;
|
int saveerrno;
|
||||||
|
|
||||||
pid = read_lockfile (h, &same_node);
|
pid = read_lockfile (h, &same_node, NULL);
|
||||||
if ( pid == -1 )
|
if ( pid == -1 )
|
||||||
{
|
{
|
||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
|
Loading…
Reference in New Issue
Block a user