Mercurial > hg > svcore
changeset 98:604bd4ee3ed4
* Add a method in System.{cpp,h} to try to establish whether a process of a
given pid is running or not
* Make TempDirectory store its process ID, and clean up any old temporary
directories it finds that correspond to non-running processes
author | Chris Cannam |
---|---|
date | Fri, 05 May 2006 11:28:04 +0000 |
parents | 22494cc28c9f |
children | 9a44ccae165c |
files | base/System.cpp base/System.h base/TempDirectory.cpp base/TempDirectory.h |
diffstat | 4 files changed, 155 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/base/System.cpp Thu May 04 20:17:28 2006 +0000 +++ b/base/System.cpp Fri May 05 11:28:04 2006 +0000 @@ -15,6 +15,21 @@ #include "System.h" +#ifdef __APPLE__ +#include <sys/types.h> +#include <sys/sysctl.h> +#else +#ifndef _WIN32 +#include <unistd.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#endif +#endif + +#include <iostream> + #ifdef _WIN32 extern "C" { @@ -34,3 +49,70 @@ } #endif + +ProcessStatus +GetProcessStatus(int pid) +{ +#ifdef __APPLE__ + + // See + // http://tuvix.apple.com/documentation/Darwin/Reference/ManPages/man3/sysctl.3.html + // http://developer.apple.com/qa/qa2001/qa1123.html + + int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0, 0 }; + name[3] = pid; + + int err; + size_t length = 0; + + if (sysctl(name, 4, 0, &length, 0, 0)) { + perror("GetProcessStatus: sysctl failed"); + return UnknownProcessStatus; + } + + if (length > 0) return ProcessRunning; + else return ProcessNotRunning; + +#elsif _WIN32 + + return UnknownProcessStatus; + +#else + + char filename[50]; + struct stat statbuf; + + // Looking up the pid in /proc is worth a try on any POSIX system, + // I guess -- it'll always compile and it won't return false + // negatives if we do this first check: + + sprintf(filename, "/proc/%d", (int)getpid()); + + int err = stat(filename, &statbuf); + + if (err || !S_ISDIR(statbuf.st_mode)) { + // If we can't even use it to tell whether we're running or + // not, then clearly /proc is no use on this system. + return UnknownProcessStatus; + } + + sprintf(filename, "/proc/%d", (int)pid); + + err = stat(filename, &statbuf); + + if (!err) { + if (S_ISDIR(statbuf.st_mode)) { + return ProcessRunning; + } else { + return UnknownProcessStatus; + } + } else if (errno == ENOENT) { + return ProcessNotRunning; + } else { + perror("stat failed"); + return UnknownProcessStatus; + } + +#endif +} +
--- a/base/System.h Thu May 04 20:17:28 2006 +0000 +++ b/base/System.h Fri May 05 11:28:04 2006 +0000 @@ -68,6 +68,9 @@ #endif /* ! _WIN32 */ +enum ProcessStatus { ProcessRunning, ProcessNotRunning, UnknownProcessStatus }; +extern ProcessStatus GetProcessStatus(int pid); + #endif /* ! _SYSTEM_H_ */
--- a/base/TempDirectory.cpp Thu May 04 20:17:28 2006 +0000 +++ b/base/TempDirectory.cpp Fri May 05 11:28:04 2006 +0000 @@ -14,6 +14,7 @@ */ #include "TempDirectory.h" +#include "System.h" #include <QDir> #include <QFile> @@ -70,8 +71,29 @@ if (m_tmpdir != "") return m_tmpdir; -//!!! QDir tempDirBase = QDir::temp(); - QDir tempDirBase = QDir::home(); + QString svDirBase = ".sv"; + QString svDir = QDir::home().filePath(svDirBase); + if (!QFileInfo(svDir).exists()) { + if (!QDir::home().mkdir(svDirBase)) { + throw DirectoryCreationFailed(QString("%1 directory in $HOME") + .arg(svDirBase)); + } + } else if (!QFileInfo(svDir).isDir()) { + throw DirectoryCreationFailed(QString("$HOME/%1 is not a directory") + .arg(svDirBase)); + } + + cleanupAbandonedDirectories(svDir); + + return createTempDirectoryIn(svDir); +} + +QString +TempDirectory::createTempDirectoryIn(QString dir) +{ + // Entered with mutex held. + + QDir tempDirBase(dir); // Generate a temporary directory. Qt4.1 doesn't seem to be able // to do this for us, and mkdtemp is not standard. This method is @@ -112,6 +134,16 @@ .arg(tempDirBase.canonicalPath())); } + QString pidpath = QDir(m_tmpdir).filePath(QString("%1.pid").arg(getpid())); + QFile pidfile(pidpath); + + if (!pidfile.open(QIODevice::WriteOnly)) { + throw DirectoryCreationFailed(QString("pid file creation in %1") + .arg(m_tmpdir)); + } else { + pidfile.close(); + } + return m_tmpdir; } @@ -196,3 +228,35 @@ m_mutex.unlock(); } } + +void +TempDirectory::cleanupAbandonedDirectories(QString svDir) +{ + QDir dir(svDir, "sv_*", QDir::Name, QDir::Dirs); + + for (unsigned int i = 0; i < dir.count(); ++i) { + + QDir subdir(dir.filePath(dir[i]), "*.pid", QDir::Name, QDir::Files); + + for (unsigned int j = 0; j < subdir.count(); ++j) { + + bool ok = false; + int pid = QFileInfo(subdir[j]).baseName().toInt(&ok); + if (!ok) continue; + + if (GetProcessStatus(pid) == ProcessNotRunning) { + std::cerr << "INFO: Found abandoned temporary directory from " + << "an old Sonic Visualiser process\n(pid=" << pid + << ", directory=\"" + << dir.filePath(dir[i]).toStdString() + << "\"). Removing it..." << std::endl; + cleanupDirectory(dir.filePath(dir[i])); + std::cerr << "...done." << std::endl; + break; + } + } + } +} + + +
--- a/base/TempDirectory.h Thu May 04 20:17:28 2006 +0000 +++ b/base/TempDirectory.h Fri May 05 11:28:04 2006 +0000 @@ -70,7 +70,11 @@ protected: TempDirectory(); + + QString createTempDirectoryIn(QString inDir); void cleanupDirectory(QString tmpDir); + void cleanupAbandonedDirectories(QString svDir); + QString m_tmpdir; QMutex m_mutex;