20 #include <klockfile.h>
24 #include <sys/types.h>
25 #ifdef HAVE_SYS_STAT_H
28 #ifdef HAVE_SYS_TIME_H
37 #include <tqtextstream.h>
40 #include <tdeapplication.h>
41 #include <tdecmdlineargs.h>
42 #include <tdeglobal.h>
43 #include <tdetempfile.h>
48 class TDELockFile::TDELockFilePrivate {
54 bool linkCountSupport;
56 KDE_struct_stat statBuf;
60 TQString lockRecoverFile;
65 TDELockFile::TDELockFile(
const TQString &file)
67 d =
new TDELockFilePrivate();
71 d->recoverLock =
false;
72 d->linkCountSupport =
true;
91 d->staleTime = _staleTime;
94 static 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);
102 static 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));
112 static 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)
174 static 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;
~TDELockFile()
Destroys the object, releasing the lock if held.
bool isLocked() const
Returns whether the lock is held or not.
The lock could not be acquired because it is held by another process.
static const char * appName()
Get the appname according to argv[0].
LockResult
Possible return values of the lock function.
void unlock()
Release the lock.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
TDEInstance * instance()
Shortcut to KNotifyClient::Instance::current() :)
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...
The KTempFile class creates and opens a unique file for temporary use.
The lock could not be acquired due to an error.
Return immediately, do not wait for the lock to become available.
A stale lock has been detected.
static int random()
Generates a uniform random number.
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
LockResult lock(int options=0)
Attempt to acquire the lock.
Lock was acquired successfully.
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds...
kdbgstream & endl(kdbgstream &s)