diff --git a/db/genelists.in b/db/genelists.in index 372a3b3a1641641b09859a66ef6659ab9769e164..ea51962fdf372d96913912bc387f713e4ff6c723 100644 --- a/db/genelists.in +++ b/db/genelists.in @@ -94,18 +94,61 @@ if (defined($newuser) && defined($allprojects)) { usage(); } -# Set up a mutex so this doesn't get run twice at the same time - +# +# We need to serialize this script to avoid a trashed map file. Use +# a dummy file in /var/tmp, opened for writing and flock'ed. +# open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n"); $count = 0; -while (flock(LOCK, LOCK_EX|LOCK_NB) == 0) { - print "Another genelists in progress. Waiting a moment ...\n"; - if ($count++ > 20) { - fatal("Could not get the lock after a long time!\n"); +if (flock(LOCK, LOCK_EX|LOCK_NB) == 0) { + # + # If we don't get it the first time, we wait for: + # 1) The lock to become free, in which case we do our thing + # 2) The time on the lock to change, in which case we wait for that process + # to finish + # + my $oldlocktime = (stat(LOCK))[9]; + my $gotlock = 0; + while (1) { + print "Another genelists in progress, waiting for it to finish\n"; + if (flock(LOCK, LOCK_EX|LOCK_NB) != 0) { + # OK, got the lock, we can do what we're supposed to + $gotlock = 1; + last; + } + $locktime = (stat(LOCK))[9]; + if ($locktime != $oldlocktime) { + $oldlocktime = $locktime; + last; + } + if ($count++ > 20) { + fatal("Could not get the lock after a long time!\n"); + } + sleep(1); + } + + $count = 0; + # + # If we didn't get the lock, wait for the processes that did to finish + # + if (!$gotlock) { + while (((stat(LOCK))[9] != $oldlocktime) && + (flock(LOCK, LOCK_EX|LOCK_NB) == 0)) { + if ($count++ > 20) { + fatal("Could not get the lock after a long time!\n"); + } + sleep(1); + } + exit(0); } - sleep(1); } +# +# Perl-style touch(1) +# +my $now = time; +utime $now, $now, $lockfile; + foreach my $active ( 0, 1 ) { my $progarg; my $userlist;