Summary: | crash if a second ktorrent instance is run with a different $DISPLAY | ||
---|---|---|---|
Product: | [Applications] ktorrent | Reporter: | Ademar de Souza Reis Jr. <ade> |
Component: | general | Assignee: | Joris Guisson <joris.guisson> |
Status: | RESOLVED FIXED | ||
Severity: | crash | ||
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Mandriva RPMs | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
Ademar de Souza Reis Jr.
2007-04-03 15:46:35 UTC
KTorrent uses KUniqueApplication to achieve the only one instance functionality, so this is a bug in kdelibs. I'm afraid it's not. KUniqueApp only guarantees one instance per KDE session - I'll make sure this is added to the documentation for KDE4 To me it would make more sense that this functionality would be implemented in KUniqueApplication, KTorrent is probably not the only app which will have problems under these circumstances. Anyway, it seems that we will have to come up with something ourselves. SVN commit 659769 by guisson: Make sure only one instance of KT can run for each user (regardless of the current $DISPLAY), this fixes bug 143791. This is implemented by a hidden lock file in the users's home directory. BUG: 143791 M +19 -28 ktorrentapp.cpp M +45 -0 main.cpp --- trunk/extragear/network/ktorrent/apps/ktorrent/ktorrentapp.cpp #659768:659769 @@ -45,40 +45,31 @@ if (!dcopClient()->isRegistered() ) dcopClient()->registerAs(name(), false); - // see if we are starting with session management -/* if (restoringSession()) + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + bt::Globals::instance().setDebugMode(args->isSet("debug")); + + QString data_dir = KGlobal::dirs()->saveLocation("data","ktorrent"); + if (!data_dir.endsWith(bt::DirSeparator())) + data_dir += bt::DirSeparator(); + bt::Globals::instance().initLog(data_dir + "log"); + + if (!mainWidget()) { - RESTORE(KTorrent); + KTorrent *widget = new KTorrent(); + setMainWidget(widget); } - else*/ - { - // no session.. just start up normally - KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); - bt::Globals::instance().setDebugMode(args->isSet("debug")); + else + KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId()); - QString data_dir = KGlobal::dirs()->saveLocation("data","ktorrent"); - if (!data_dir.endsWith(bt::DirSeparator())) - data_dir += bt::DirSeparator(); - bt::Globals::instance().initLog(data_dir + "log"); - if (!mainWidget()) - { - KTorrent *widget = new KTorrent(); - setMainWidget(widget); - } - else - KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId()); + KTorrent *widget = ::qt_cast<KTorrent*>( mainWidget() ); - - KTorrent *widget = ::qt_cast<KTorrent*>( mainWidget() ); - - for (int i = 0; i < args->count(); i++) - { - widget->load(args->url(i)); - } - - args->clear(); + for (int i = 0; i < args->count(); i++) + { + widget->load(args->url(i)); } + + args->clear(); return 0; } --- trunk/extragear/network/ktorrent/apps/ktorrent/main.cpp #659768:659769 @@ -34,14 +34,25 @@ #include <qapplication.h> #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <errno.h> +#include <fcntl.h> #include <util/error.h> #include <util/log.h> #include <torrent/globals.h> +#include <util/fileops.h> #include <ktversion.h> +#include <functions.h> +#include <qfile.h> +#include <qdir.h> using namespace bt; + void StupidWarningMessagesFromQt( QtMsgType type, const char *msg ) { switch ( type ) @@ -60,11 +71,38 @@ } + static const char description[] = I18N_NOOP("A BitTorrent program for KDE"); +bool GrabPIDLock() +{ + // open the PID file in the users ktorrent directory and attempt to lock it + QString pid_file = QDir::homeDirPath() + "/.ktorrent.lock"; + + int fd = open(QFile::encodeName(pid_file),O_RDWR|O_CREAT,0640); + if (fd < 0) + { + fprintf(stderr,"Failed to open KT lock file %s : %s\n",pid_file.ascii(),strerror(errno)); + return false; + } + if (lockf(fd,F_TLOCK,0)<0) + { + fprintf(stderr,"Failed to get lock on %s : %s\n",pid_file.ascii(),strerror(errno)); + return false; + } + + char str[20]; + sprintf(str,"%d\n",getpid()); + write(fd,str,strlen(str)); /* record pid to lockfile */ + + // leave file open, so nobody else can lock it until KT exists + return true; +} + + static KCmdLineOptions options[] = { { "debug", I18N_NOOP("Debug mode"), 0 }, @@ -120,6 +158,13 @@ fprintf(stderr, "ktorrent is already running!\n"); return 0; } + + // need to grab lock after the fork call in start, otherwise this will not work properly + if (!GrabPIDLock()) + { + fprintf(stderr, "ktorrent is already running!\n"); + return 0; + } try { |