37#include <tqtextstream.h> 
   40#include <tdeapplication.h> 
   41#include <tdecmdlineargs.h> 
   43#include <tdetempfile.h> 
   48class TDELockFile::TDELockFilePrivate {
 
   54   bool linkCountSupport;
 
   56   KDE_struct_stat statBuf;
 
   60   TQString lockRecoverFile;
 
   65TDELockFile::TDELockFile(
const TQString &file)
 
   67  d = 
new TDELockFilePrivate();
 
   71  d->recoverLock = 
false;
 
   72  d->linkCountSupport = 
true;
 
   91  d->staleTime = _staleTime;
 
   94static bool statResultIsEqual(KDE_struct_stat &st_buf1, KDE_struct_stat &st_buf2)
 
   96#define FIELD_EQ(what)       (st_buf1.what == st_buf2.what) 
   97  return FIELD_EQ(st_dev) && FIELD_EQ(st_ino) && 
 
   98         FIELD_EQ(st_uid) && FIELD_EQ(st_gid) && FIELD_EQ(st_nlink);
 
  102static bool testLinkCountSupport(
const TQCString &fileName)
 
  104   KDE_struct_stat st_buf;
 
  106   ::link( fileName, fileName+
".test" );
 
  107   int result = KDE_lstat( fileName, &st_buf );
 
  108   ::unlink( fileName+
".test" );
 
  109   return ((result == 0) && (st_buf.st_nlink == 2));
 
  112static TDELockFile::LockResult lockFile(
const TQString &lockFile, KDE_struct_stat &st_buf, 
bool &linkCountSupport)
 
  114  TQCString lockFileName = TQFile::encodeName( lockFile );
 
  115  int result = KDE_lstat( lockFileName, &st_buf );
 
  119  KTempFile uniqueFile(lockFile, TQString::null, 0644);
 
  120  uniqueFile.setAutoDelete(
true);
 
  121  if (uniqueFile.status() != 0)
 
  126  gethostname(hostname, 255);
 
  130  (*(uniqueFile.textStream())) << TQString::number(getpid()) << 
endl 
  131      << instanceName << 
endl 
  135  TQCString uniqueName = TQFile::encodeName( uniqueFile.name() );
 
  139  result = ::link( uniqueName, lockFileName );
 
  143  if (!linkCountSupport)
 
  150  KDE_struct_stat st_buf2;
 
  151  result = KDE_lstat( uniqueName, &st_buf2 );
 
  155  result = KDE_lstat( lockFileName, &st_buf );
 
  159  if (!statResultIsEqual(st_buf, st_buf2) || S_ISLNK(st_buf.st_mode) || S_ISLNK(st_buf2.st_mode))
 
  162     if ((st_buf.st_nlink == 1) && (st_buf2.st_nlink == 1) && (st_buf.st_ino != st_buf2.st_ino))
 
  164        linkCountSupport = testLinkCountSupport(uniqueName);
 
  165        if (!linkCountSupport)
 
  174static TDELockFile::LockResult deleteStaleLock(
const TQString &lockFile, KDE_struct_stat &st_buf, 
bool &linkCountSupport)
 
  181   if (ktmpFile.status() != 0)
 
  184   TQCString lckFile = TQFile::encodeName(lockFile);
 
  185   TQCString tmpFile = TQFile::encodeName(ktmpFile.name());
 
  191   if (::link(lckFile, tmpFile) != 0)
 
  200   KDE_struct_stat st_buf1;
 
  201   KDE_struct_stat st_buf2;
 
  202   memcpy(&st_buf1, &st_buf, 
sizeof(KDE_struct_stat));
 
  204   if ((KDE_lstat(tmpFile, &st_buf2) == 0) && statResultIsEqual(st_buf1, st_buf2))
 
  206      if ((KDE_lstat(lckFile, &st_buf2) == 0) && statResultIsEqual(st_buf1, st_buf2))
 
  209         tqWarning(
"[tdecore] Deleting stale lockfile %s", lckFile.data());
 
  217   if (linkCountSupport)
 
  219      linkCountSupport = testLinkCountSupport(tmpFile);
 
  222   if (!linkCountSupport && 
 
  223       (KDE_lstat(lckFile, &st_buf2) == 0) && 
 
  224       statResultIsEqual(st_buf, st_buf2))
 
  227      tqWarning(
"[tdecore] Deleting stale lockfile %s", lckFile.data());
 
  234   tqWarning(
"[tdecore] WARNING: Problem deleting stale lockfile %s", lckFile.data());
 
  250     KDE_struct_stat st_buf;
 
  251     result = lockFile(d->file, st_buf, d->linkCountSupport);
 
  254        d->staleTimer = TQTime();
 
  259        d->staleTimer = TQTime();
 
  260        if (--hardErrors == 0)
 
  267        if (!d->staleTimer.isNull() && !statResultIsEqual(d->statBuf, st_buf))
 
  268           d->staleTimer = TQTime();
 
  270        if (!d->staleTimer.isNull())
 
  272           bool isStale = 
false;
 
  273           if ((d->pid > 0) && !d->hostname.isEmpty())
 
  278              gethostname(hostname, 255);
 
  281              if (d->hostname == hostname)
 
  284                 int res = ::kill(d->pid, 0);
 
  285                 if ((res == -1) && (errno == ESRCH))
 
  289           if (d->staleTimer.elapsed() > (d->staleTime*1000))
 
  297              result = deleteStaleLock(d->file, d->statBuf, d->linkCountSupport);
 
  302                 d->staleTimer = TQTime();
 
  313           memcpy(&(d->statBuf), &st_buf, 
sizeof(KDE_struct_stat));
 
  314           d->staleTimer.start();
 
  317           d->hostname = TQString::null;
 
  318           d->instance = TQString::null;
 
  320           TQFile file(d->file);
 
  321           if (file.open(IO_ReadOnly))
 
  323              TQTextStream ts(&file);
 
  325                 d->pid = ts.readLine().toInt();
 
  327                 d->instance = ts.readLine();
 
  329                 d->hostname = ts.readLine();
 
  344     select(0, 0, 0, 0, &tv);
 
  363     ::unlink(TQFile::encodeName(d->file));
 
  373  hostname = d->hostname;
 
  374  appname = d->instance;
 
The KTempFile class creates and opens a unique file for temporary use.
static int random()
Generates a uniform random number.
static const char * appName()
Get the appname according to argv[0].
LockResult
Possible return values of the lock function.
@ LockStale
A stale lock has been detected.
@ LockError
The lock could not be acquired due to an error.
@ LockOK
Lock was acquired successfully.
@ LockFail
The lock could not be acquired because it is held by another process.
@ LockForce
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds.
@ LockNoBlock
Return immediately, do not wait for the lock to become available.
bool isLocked() const
Returns whether the lock is held or not.
void unlock()
Release the lock.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
LockResult lock(int options=0)
Attempt to acquire the lock.
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
~TDELockFile()
Destroys the object, releasing the lock if held.
bool getLockInfo(int &pid, TQString &hostname, TQString &appname)
Returns the pid, hostname and appname of the process holding the lock after the lock functon has retu...
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
TDEInstance * instance()
Shortcut to KNotifyClient::Instance::current() :)