From eca5f2e81a7c859bfbd378b5f5cd7c7b5d4ba0b0 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Fri, 12 Sep 2008 22:00:46 +0000 Subject: * implemented support for recursive file-based locks * used improved locking mechanism to protect not only slxconfig-demuxer against being executed twice, but also to avoid two different process groups from chrooting into the same vendor-OS git-svn-id: http://svn.openslx.org/svn/openslx/openslx/trunk@2213 95ad53e4-c205-0410-b2fa-d234c58c8868 --- config-db/slxconfig-demuxer | 44 +--------------- installer/OpenSLX/OSSetup/Engine.pm | 3 ++ lib/OpenSLX/Basics.pm | 1 + lib/OpenSLX/Utils.pm | 95 ++++++++++++++++++++++++++++++----- os-plugins/OpenSLX/OSPlugin/Engine.pm | 6 ++- 5 files changed, 94 insertions(+), 55 deletions(-) diff --git a/config-db/slxconfig-demuxer b/config-db/slxconfig-demuxer index 7234b762..942b8a88 100755 --- a/config-db/slxconfig-demuxer +++ b/config-db/slxconfig-demuxer @@ -31,7 +31,6 @@ slxconfig-demuxer use Config::General; use Digest::MD5 qw(md5_hex); -use Fcntl qw(:DEFAULT :flock); use File::Basename; use File::Find; use File::Path; @@ -50,7 +49,6 @@ use OpenSLX::Basics; use OpenSLX::ConfigDB qw(:support); use OpenSLX::ConfigFolder; use OpenSLX::OSPlugin::Roster; -use OpenSLX::ScopedResource; use OpenSLX::Utils; my ( @@ -110,46 +108,8 @@ if (createConfigFolderForDefaultSystem()) { ); } -# protect against parallel executions of this script -my $criticalSection = OpenSLX::ScopedResource->new({ - name => 'osplugin::session', - acquire => sub { - return if $option{dryRun}; - - # use a lock-file to singularize execution of this script: - my $lockFile = "$openslxConfig{'private-path'}/config-demuxer.lock"; - if (-e $lockFile) { - my $ctime = (stat($lockFile))[10]; - my $now = time(); - if ($now - $ctime > 15 * 60) { - # existing lock file is older than 15 minutes, wipe it: - unlink $lockFile; - } - } - if (!sysopen(LOCKFILE, $lockFile, O_RDWR | O_CREAT | O_EXCL)) { - if ($! == 13) { - die _tr(qq[Unable to create lock-file <%s>, exiting!\n], $lockFile); - } else { - die _tr(unshiftHereDoc(<<" End-of-Here"), - Lock-file '%s' exists, script is already running. - Please remove the logfile and try again if you are sure that no one else - is executing this script. - End-of-Here - $lockFile - ); - } - } - 1 - }, - release => sub { - return if $option{dryRun}; - - my $lockFile = "$openslxConfig{'private-path'}/config-demuxer.lock"; - close(LOCKFILE); - unlink $lockFile; - 1 - }, -}); +# protect against parallel executions of writing OpenSLX scripts +my $globalLock = grabLock('global'); my $tempPath = "$openslxConfig{'temp-path'}/slxconfig-demuxer"; if (!$option{dryRun}) { diff --git a/installer/OpenSLX/OSSetup/Engine.pm b/installer/OpenSLX/OSSetup/Engine.pm index 2a4801ae..47ba9b3c 100644 --- a/installer/OpenSLX/OSSetup/Engine.pm +++ b/installer/OpenSLX/OSSetup/Engine.pm @@ -140,6 +140,9 @@ sub initialize $distro->initialize($self); $self->{distro} = $distro; + # protect against parallel executions of writing OpenSLX scripts + $self->{'vendor-os-lock'} = grabLock($vendorOSName); + if ($actionType =~ m{^(install|update|shell|plugin)}) { # setup path to distribution-specific info: my $sharedDistroInfoDir diff --git a/lib/OpenSLX/Basics.pm b/lib/OpenSLX/Basics.pm index 5b43f155..581e6e49 100644 --- a/lib/OpenSLX/Basics.pm +++ b/lib/OpenSLX/Basics.pm @@ -842,6 +842,7 @@ sub _doThrowOrWarn return; } + =back =cut diff --git a/lib/OpenSLX/Utils.pm b/lib/OpenSLX/Utils.pm index 6ebd4d7c..0ce253b9 100644 --- a/lib/OpenSLX/Utils.pm +++ b/lib/OpenSLX/Utils.pm @@ -23,18 +23,19 @@ $VERSION = 1.01; @ISA = qw(Exporter); @EXPORT = qw( - copyFile fakeFile linkFile - copyBinaryWithRequiredLibs - slurpFile spitFile appendFile - followLink - unshiftHereDoc - string2Array - chrootInto - mergeHash - getFQDN - readPassword - hostIs64Bit - getAvailableBusyboxApplets + copyFile fakeFile linkFile + copyBinaryWithRequiredLibs + slurpFile spitFile appendFile + followLink + unshiftHereDoc + string2Array + chrootInto + mergeHash + getFQDN + readPassword + hostIs64Bit + getAvailableBusyboxApplets + grabLock ); =head1 NAME @@ -48,6 +49,7 @@ OpenSLX. =cut +use Fcntl qw(:DEFAULT :flock); use File::Basename; use File::Path; use Socket; @@ -55,6 +57,7 @@ use Sys::Hostname; use Term::ReadLine; use OpenSLX::Basics; +use OpenSLX::ScopedResource; =head1 PUBLIC FUNCTIONS @@ -584,4 +587,72 @@ sub getAvailableBusyboxApplets return @busyboxApplets; } +=item grabLock() + +=cut + +sub grabLock +{ + my $lockName = shift || die 'you need to pass a lock-name to grabLock()!'; + + my $lockPath = "$openslxConfig{'private-path'}/locks"; + mkpath($lockPath) unless -e $lockPath; + my $lockFile = "$lockPath/$lockName"; + + my $lockFH; + + my $lock = OpenSLX::ScopedResource->new({ + name => "lock::$lockName", + acquire => sub { + # use a lock-file to implement the actual locking: + if (-e $lockFile) { + my $ctime = (stat($lockFile))[10]; + my $now = time(); + if ($now - $ctime > 15 * 60) { + # existing lock file is older than 15 minutes, we consider + # that to be a leftover (which shouldn't happen of course) + # and wipe it: + unlink $lockFile; + } + } + + local $| = 1; + my $waiting; + while(!(sysopen($lockFH, $lockFile, O_RDWR | O_CREAT | O_EXCL) + && print $lockFH getpgrp() . "\n")) { + if ($! == 13) { + die _tr( + qq[Unable to create lock "%s", giving up!], $lockFile + ); + } else { + # check if the lock is owned by our own process group + # and only block if it isn't (this allows recursive locking) + my $pgrpOfLock + = slurpFile($lockFile, { failIfMissing => 0}); + last if $pgrpOfLock && $pgrpOfLock == getpgrp(); + + # wait for lock to become available + if (!$waiting) { + print _tr('waiting for "%s"-lock ', $lockName); + $waiting = 1; + } + else { + print '.'; + } + sleep(1); + } + } + print "ok\n" if $waiting; + 1 + }, + release => sub { + close($lockFH); + unlink $lockFile; + 1 + }, + }); + + return $lock; +} + 1; diff --git a/os-plugins/OpenSLX/OSPlugin/Engine.pm b/os-plugins/OpenSLX/OSPlugin/Engine.pm index 5488b4ac..c5e6a99f 100644 --- a/os-plugins/OpenSLX/OSPlugin/Engine.pm +++ b/os-plugins/OpenSLX/OSPlugin/Engine.pm @@ -627,6 +627,10 @@ sub _callChrootedFunctionForPlugin my $self = shift; my $function = shift; + # create os-setup engine here in order to block access to the vendor-OS + # via other processes (which could cause problems) + my $osSetupEngine = $self->_osSetupEngine(); + # bind-mount openslx basepath to /mnt/openslx of vendor-OS: my $basePath = $openslxConfig{'base-path'}; my $basePathInChroot = "$self->{'vendor-os-path'}/mnt/opt/openslx"; @@ -667,7 +671,7 @@ sub _callChrootedFunctionForPlugin }); # now let plugin install itself into vendor-OS - $self->_osSetupEngine()->callChrootedFunctionForVendorOS($function); + $osSetupEngine->callChrootedFunctionForVendorOS($function); return; } -- cgit v1.2.3-55-g7522