32 #include <boost/interprocess/sync/file_lock.hpp> 33 #include <boost/interprocess/sync/scoped_lock.hpp> 34 #include <boost/interprocess/sync/sharable_lock.hpp> 39 using boost::interprocess::file_lock;
40 using boost::interprocess::scoped_lock;
41 using boost::interprocess::sharable_lock;
68 template class SigBacktraceHandler<SIGSEGV>;
69 template class SigBacktraceHandler<SIGABRT>;
76 {
return getenv(
"ZYPP_LOCKFILE_ROOT") ? getenv(
"ZYPP_LOCKFILE_ROOT") :
"/"; }
80 namespace zypp_readonly_hack
83 static bool active = getenv(
"ZYPP_READONLY_HACK");
88 MIL <<
"ZYPP_READONLY promised." << endl;
109 : _zyppLockFilePath(
std::move(lFilePath)), _zyppLockFile(NULL),
110 _lockerPid(0), _cleanLock(false) {
126 scoped_lock<file_lock> flock( _zyppLockFileLock );
129 ftruncate( fileno(_zyppLockFile), 0 );
131 MIL <<
"Cleaned lock file. (" << getpid() <<
")" << std::endl;
137 {
return _lockerPid; }
140 {
return _lockerName; }
143 {
return _zyppLockFilePath; }
174 if ( _zyppLockFile != NULL )
178 _zyppLockFile = fopen( _zyppLockFilePath.
c_str(),
"a+" );
179 if ( _zyppLockFile == NULL )
181 _zyppLockFileLock = _zyppLockFilePath.
c_str();
182 MIL <<
"Open lockfile " << _zyppLockFilePath << endl;
188 if ( _zyppLockFile == NULL )
191 clearerr( _zyppLockFile );
192 fflush( _zyppLockFile );
197 _zyppLockFileLock = file_lock();
198 fclose( _zyppLockFile );
199 _zyppLockFile = NULL;
200 MIL <<
"Close lockfile " << _zyppLockFilePath << endl;
209 MIL <<
"Checking " << status << endl;
211 if ( ! status.
isDir() )
213 DBG <<
"No such process." << endl;
217 static char buffer[513];
218 buffer[0] = buffer[512] = 0;
220 if ( std::ifstream( (procdir/
"cmdline").c_str() ).read( buffer, 512 ).gcount() > 0 )
222 _lockerName = buffer;
223 DBG <<
"Is running: " << _lockerName << endl;
227 DBG <<
"In zombie state." << endl;
233 clearerr( _zyppLockFile );
234 fseek( _zyppLockFile, 0, SEEK_SET );
236 fscanf( _zyppLockFile,
"%ld", &readpid );
237 MIL <<
"read: Lockfile " << _zyppLockFilePath <<
" has pid " << readpid <<
" (our pid: " << getpid() <<
") "<< std::endl;
238 return (pid_t)readpid;
243 clearerr( _zyppLockFile );
244 fseek( _zyppLockFile, 0, SEEK_SET );
245 ftruncate( fileno(_zyppLockFile), 0 );
246 fprintf(_zyppLockFile,
"%ld\n", (
long)getpid() );
247 fflush( _zyppLockFile );
249 MIL <<
"write: Lockfile " << _zyppLockFilePath <<
" got pid " << getpid() << std::endl;
257 _lockerPid = readLockFile();
258 if ( _lockerPid == 0 ) {
261 }
else if ( _lockerPid == getpid() ) {
266 if ( isProcessRunning( _lockerPid ) ) {
267 WAR << _lockerPid <<
" is running and has a ZYpp lock. Sorry." << std::endl;
270 MIL << _lockerPid <<
" is dead. Ignoring the existing lock file." << std::endl;
280 if ( geteuid() != 0 )
285 scoped_lock<file_lock> flock( _zyppLockFileLock );
286 return safeCheckIsLocked ();
294 if ( geteuid() != 0 )
299 scoped_lock<file_lock> flock( _zyppLockFileLock );
300 if ( !safeCheckIsLocked() ) {
315 ZYppGlobalLock & globalLock()
317 if ( !_theGlobalLock )
319 return *_theGlobalLock;
334 MIL <<
"ZYpp is on..." << endl;
339 _theGlobalLock.reset();
340 MIL <<
"ZYpp is off..." << endl;
351 , _lockerPid( lockerPid_r )
352 , _lockerName(
std::move( lockerName_r ))
378 const auto &makeLockedError = []( pid_t pid,
const std::string &lockerName ){
379 const std::string &t =
str::form(
_(
"System management is locked by the application with pid %d (%s).\n" 380 "Close this application before trying again."), pid, lockerName.c_str() );
384 ZYpp::Ptr _instance = _theZYppInstance.lock();
387 if ( geteuid() != 0 )
389 MIL <<
"Running as user. Skip creating " << globalLock().zyppLockFilePath() << std::endl;
393 MIL <<
"ZYPP_READONLY active." << endl;
395 else if ( globalLock().zyppLocked() )
399 const long LOCK_TIMEOUT = str::strtonum<long>( getenv(
"ZYPP_LOCK_TIMEOUT" ) );
400 if ( LOCK_TIMEOUT != 0 )
404 if ( LOCK_TIMEOUT > 0 ) {
405 giveup = logwait+LOCK_TIMEOUT;
406 MIL <<
"$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT <<
" sec. Waiting for the zypp lock until " << giveup << endl;
409 MIL <<
"$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT <<
" sec. Waiting for the zypp lock..." << endl;
418 WAR <<
"$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT <<
" sec. Another day has passed waiting for the zypp lock..." << endl;
425 failed = globalLock().zyppLocked();
427 }
while ( failed && ( not giveup ||
Date::now() <= giveup ) );
430 MIL <<
"$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT <<
" sec. Gave up waiting for the zypp lock." << endl;
433 MIL <<
"$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT <<
" sec. Finally got the zypp lock." << endl;
437 ZYPP_THROW( makeLockedError( globalLock().lockerPid(), globalLock().lockerName() ));
444 _theGlobalLock.reset();
452 if ( !_theImplInstance )
454 _instance.reset(
new ZYpp( _theImplInstance ) );
455 _theZYppInstance = _instance;
464 {
return !_theZYppInstance.expired(); }
478 return str <<
"ZYppFactory";
ScopedGuard accessLockFile()
Exception safe access to the lockfile.
static const ValueType day
Namespace intended to collect all environment variables we use.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
shared_ptr< void > ScopedGuard
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
bool haveZYpp() const
Whether the ZYpp instance is already created.
void IWantIt() ZYPP_DEPRECATED
const char * c_str() const
String representation.
const std::string & lockerName() const
String related utilities and Regular expression matching.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Pathname ZYPP_LOCKFILE_ROOT()
Hack to circumvent the currently poor –root support.
ZYppFactoryException(std::string msg_r, pid_t lockerPid_r, std::string lockerName_r)
static ZYppFactory instance()
Singleton ctor.
Exchange LineWriter for the lifetime of this object.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
ZYpp(const Impl_Ptr &impl_r)
Factory ctor.
bool isProcessRunning(pid_t pid_r)
~ZYppFactoryException() override
static LogControl instance()
Singleton access.
Pathname _zyppLockFilePath
Store and operate on date (time_t).
::sighandler_t lastSigHandler
const std::string & asString() const
String representation.
const Arch Arch_armv7hnl Arch_armv7nhl ZYPP_API
ZYpp::Ptr getZYpp() const
ZYpp factory class (Singleton)
ZYppFactory()
Default ctor.
const Pathname & zyppLockFilePath() const
ZYppGlobalLock(Pathname &&lFilePath)
shared_ptr< Impl > Impl_Ptr
std::string numstring(char n, int w=0)
static void backtraceHandler(int sig)
void _closeLockFile()
Use accessLockFile.
constexpr std::string_view FILE("file")
Base class for Exception.
static Date now()
Return the current time.
Signal handler logging a stack trace.
Wrapper class for ::stat/::lstat.
bool zyppLocked()
Try to aquire a lock.
static zypp::Pathname lockfileDir()
void _openLockFile()
Use accessLockFile.
Easy-to use interface to the ZYPP dependency resolver.
void emergencyShutdown()
will cause the log thread to exit and flush all sockets
std::ostream & dumpBacktrace(std::ostream &stream_r)
Dump current stack trace to a stream.
void repoVariablesReset()
file_lock _zyppLockFileLock