All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 21b37a35 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Add serialization (the usual locking code) to prevent corruption of

the .htpasswd file on ops. Note that I have disabled registration and
password changes from the twiki interface on ops for now. I'll think
about this as needed.
parent 98ad1058
......@@ -6,6 +6,7 @@
#
use English;
use Getopt::Std;
use Fcntl ':flock';
#
# Add a user to the wiki on ops. Also allow update of password.
......@@ -29,6 +30,7 @@ my $BOSSNODE = "@BOSSNODE@";
my $WIKISUPPORT = @WIKISUPPORT@;
my $SSH = "$TB/bin/sshtb";
my $WIKIPROXY = "$TB/sbin/wikiproxy";
my $lockfile = "/var/tmp/testbed_wikiuser_lockfile";
#
# Untaint the path
......@@ -102,6 +104,70 @@ else {
die("Bad data in user: $user.");
}
#
# 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.
#
if (1) {
open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n");
$count = 0;
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 exports update 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 (1) {
if ((stat(LOCK))[9] != $oldlocktime) {
exit(0);
}
if (flock(LOCK, LOCK_EX|LOCK_NB) != 0) {
close(LOCK);
exit(0);
}
if ($count++ > 30) {
fatal("Process with the lock did not finish ".
"after a long time!\n");
}
sleep(1);
}
}
}
}
#
# Perl-style touch(1)
#
my $now = time;
utime $now, $now, $lockfile;
#
# This script always does the right thing, so no permission checks.
# In fact, all it does it call over to ops to run a script over there.
......@@ -123,6 +189,10 @@ if (!$query_result->numrows) {
my ($wikiname,$usr_name,$usr_email) = $query_result->fetchrow_array();
if (!defined($wikiname)) {
# In update mode, do nothing if no wikiname.
exit(0)
if ($update);
my @tokens = split(/\s+|-/, $usr_name);
#
......
......@@ -6,6 +6,7 @@
#
use English;
use Getopt::Std;
use Fcntl ':flock';
#
# Delete a user from the wiki
......@@ -28,6 +29,7 @@ my $BOSSNODE = "@BOSSNODE@";
my $WIKISUPPORT = @WIKISUPPORT@;
my $SSH = "$TB/bin/sshtb";
my $WIKIPROXY = "$TB/sbin/wikiproxy";
my $lockfile = "/var/tmp/testbed_wikiuser_lockfile";
#
# Untaint the path
......@@ -98,6 +100,70 @@ else {
die("Bad data in user: $user.");
}
#
# 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.
#
if (1) {
open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n");
$count = 0;
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 exports update 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 (1) {
if ((stat(LOCK))[9] != $oldlocktime) {
exit(0);
}
if (flock(LOCK, LOCK_EX|LOCK_NB) != 0) {
close(LOCK);
exit(0);
}
if ($count++ > 30) {
fatal("Process with the lock did not finish ".
"after a long time!\n");
}
sleep(1);
}
}
}
}
#
# Perl-style touch(1)
#
my $now = time;
utime $now, $now, $lockfile;
#
# This script always does the right thing, so no permission checks.
# In fact, all it does it call over to ops to run a script over there.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment