-rw-r--r-- | core/launcher/applauncher.cpp | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/core/launcher/applauncher.cpp b/core/launcher/applauncher.cpp index 50c1b71..d6f93da 100644 --- a/core/launcher/applauncher.cpp +++ b/core/launcher/applauncher.cpp @@ -18,25 +18,25 @@ ** **********************************************************************/ #ifndef QTOPIA_INTERNAL_PRELOADACCESS #define QTOPIA_INTERNAL_PRELOADACCESS #endif #ifndef QTOPIA_INTERNAL_FILEOPERATIONS #define QTOPIA_INTERNAL_FILEOPERATIONS #endif #ifndef QTOPIA_PROGRAM_MONITOR #define QTOPIA_PROGRAM_MONITOR #endif -#include <qtopia/qpeglobal.h> +#include <qtopia/global.h> #ifndef Q_OS_WIN32 #include <sys/stat.h> #include <sys/wait.h> #include <sys/file.h> #include <unistd.h> #include <sys/time.h> #include <sys/resource.h> #include <errno.h> #else #include <process.h> #include <windows.h> @@ -52,115 +52,116 @@ #include <qmessagebox.h> #include <qfile.h> #include <qfileinfo.h> #include <qtopia/qcopenvelope_qws.h> #include <qtopia/applnk.h> #include <qtopia/qpeapplication.h> #include <qtopia/config.h> #include <qtopia/global.h> #include "applauncher.h" #include "documentlist.h" +#include "launcherglobal.h" const int AppLauncher::RAISE_TIMEOUT_MS = 5000; //--------------------------------------------------------------------------- static AppLauncher* appLauncherPtr; const int appStopEventID = 1290; class AppStoppedEvent : public QCustomEvent { public: AppStoppedEvent(int pid, int status) : QCustomEvent( appStopEventID ), mPid(pid), mStatus(status) { } - + int pid() { return mPid; } int status() { return mStatus; } private: int mPid, mStatus; }; AppLauncher::AppLauncher(QObject *parent, const char *name) : QObject(parent, name), qlPid(0), qlReady(FALSE), appKillerBox(0) { connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&))); connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&))); QCopChannel* channel = new QCopChannel( "QPE/System", this ); connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), this, SLOT(received(const QCString&, const QByteArray&)) ); channel = new QCopChannel( "QPE/Server", this ); connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), this, SLOT(received(const QCString&, const QByteArray&)) ); - + #ifndef Q_OS_WIN32 signal(SIGCHLD, signalHandler); #else runningAppsProc.setAutoDelete( TRUE ); #endif QString tmp = qApp->argv()[0]; int pos = tmp.findRev('/'); if ( pos > -1 ) tmp = tmp.mid(++pos); runningApps[::getpid()] = tmp; - + appLauncherPtr = this; QTimer::singleShot( 1000, this, SLOT(createQuickLauncher()) ); } AppLauncher::~AppLauncher() { appLauncherPtr = 0; #ifndef Q_OS_WIN32 signal(SIGCHLD, SIG_DFL); #endif if ( qlPid ) { int status; ::kill( qlPid, SIGTERM ); waitpid( qlPid, &status, 0 ); } } /* We use the QCopChannel of the app as an indicator of when it has been launched so that we can disable the busy indicators */ -void AppLauncher::newQcopChannel(const QString& channelName) +void AppLauncher::newQcopChannel(const QString& channelName) { // qDebug("channel %s added", channelName.data() ); QString prefix("QPE/Application/"); if (channelName.startsWith(prefix)) { { QCopEnvelope e("QPE/System", "newChannel(QString)"); e << channelName; } QString appName = channelName.mid(prefix.length()); if ( appName != "quicklauncher" ) { emit connected( appName ); QCopEnvelope e("QPE/System", "notBusy(QString)"); e << appName; } } else if (channelName.startsWith("QPE/QuickLauncher-")) { qDebug("Registered %s", channelName.latin1()); int pid = channelName.mid(18).toInt(); if (pid == qlPid) qlReady = TRUE; } } -void AppLauncher::removedQcopChannel(const QString& channelName) +void AppLauncher::removedQcopChannel(const QString& channelName) { if (channelName.startsWith("QPE/Application/")) { QCopEnvelope e("QPE/System", "removedChannel(QString)"); e << channelName; } } void AppLauncher::received(const QCString& msg, const QByteArray& data) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "execute(QString)" ) { QString t; @@ -250,72 +251,72 @@ void AppLauncher::signalHandler(int) #else qDebug("Unhandled signal see by AppLauncher::signalHandler(int)"); #endif } bool AppLauncher::event(QEvent *e) { if ( e->type() == appStopEventID ) { AppStoppedEvent *ae = (AppStoppedEvent *) e; sigStopped(ae->pid(), ae->status() ); return TRUE; } - + return QObject::event(e); } void AppLauncher::timerEvent( QTimerEvent *e ) { int id = e->timerId(); QMap<QString,int>::Iterator it; for ( it = waitingHeartbeat.begin(); it != waitingHeartbeat.end(); ++it ) { if ( *it == id ) { if ( appKillerBox ) // we're already dealing with one return; appKillerName = it.key(); killTimer( id ); waitingHeartbeat.remove( it ); // qDebug("Checking in on %s", appKillerName.latin1()); // We store this incase the application responds while we're // waiting for user input so we know not to delete ourselves. appKillerBox = new QMessageBox(tr("Application Problem"), tr("<p>%1 is not responding.</p>").arg(appKillerName) + - tr("<p>Would you like to force the application to exit?</p>"), - QMessageBox::Warning, QMessageBox::Yes, - QMessageBox::No | QMessageBox::Default, + tr("<p>Would you like to force the application to exit?</p>"), + QMessageBox::Warning, QMessageBox::Yes, + QMessageBox::No | QMessageBox::Default, QMessageBox::NoButton); - if (appKillerBox->exec() == QMessageBox::Yes) { + if (appKillerBox->exec() == QMessageBox::Yes) { // qDebug("Killing the app!!! Bwuhahahaha!"); int pid = pidForName(appKillerName); if ( pid > 0 ) kill( pid ); } appKillerName = QString::null; delete appKillerBox; appKillerBox = 0; return; } } QObject::timerEvent( e ); } -#ifndef Q_OS_WIN32 +#ifndef Q_OS_WIN32 void AppLauncher::sigStopped(int sigPid, int sigStatus) { int exitStatus = 0; - + bool crashed = WIFSIGNALED(sigStatus); if ( !crashed ) { if ( WIFEXITED(sigStatus) ) exitStatus = WEXITSTATUS(sigStatus); } else { exitStatus = WTERMSIG(sigStatus); } QMap<int,QString>::Iterator it = runningApps.find( sigPid ); if ( it == runningApps.end() ) { if ( sigPid == qlPid ) { qDebug( "quicklauncher stopped" ); @@ -355,30 +356,30 @@ void AppLauncher::sigStopped(int sigPid, int sigStatus) const AppLnk* app = DocumentList::appLnkSet->findExec( appName ); if ( !app ) return; // QCop messages processed to slow? if ( crashed && app->isPreloaded() ) { Config cfg("Launcher"); cfg.setGroup("Preload"); QStringList apps = cfg.readListEntry("Apps",','); QString exe = app->exec(); apps.remove(exe); cfg.writeEntry("Apps",apps,','); preloadDisabled = TRUE; } - // clean up + // clean up if ( exitStatus ) { QCopEnvelope e("QPE/System", "notBusy(QString)"); e << app->exec(); } -/* +/* // debug info for (it = runningApps.begin(); it != runningApps.end(); ++it) { qDebug("running according to internal list: %s, with pid %d", (*it).data(), it.key() ); } */ #ifdef QTOPIA_PROGRAM_MONITOR if ( crashed ) { QString sig; switch( exitStatus ) { case SIGABRT: sig = "SIGABRT"; break; case SIGALRM: sig = "SIGALRM"; break; @@ -387,42 +388,43 @@ void AppLauncher::sigStopped(int sigPid, int sigStatus) case SIGHUP: sig = "SIGHUP"; break; case SIGILL: sig = "SIGILL"; break; case SIGKILL: sig = "SIGKILL"; break; case SIGPIPE: sig = "SIGPIPE"; break; case SIGQUIT: sig = "SIGQUIT"; break; case SIGSEGV: sig = "SIGSEGV"; break; case SIGTERM: sig = "SIGTERM"; break; case SIGTRAP: sig = "SIGTRAP"; break; default: sig = QString("Unkown %1").arg(exitStatus); } if ( preloadDisabled ) sig += tr("<qt><p>Fast loading has been disabled for this application. Tap and hold the application icon to reenable it.</qt>"); - + QString str = tr("<qt><b>%1</b> was terminated due to signal code %2</qt>").arg( app->name() ).arg( sig ); QMessageBox::information(0, tr("Application terminated"), str ); } else { if ( exitStatus == 255 ) { //could not find app (because global returns -1) QMessageBox::information(0, tr("Application not found"), tr("<qt>Could not locate application <b>%1</b></qt>").arg( app->exec() ) ); } else { - QFileInfo fi(Global::tempDir() + "qcop-msg-" + appName); + QFileInfo fi(Opie::Global::tempDir() + "qcop-msg-" + appName); if ( fi.exists() && fi.size() ) { emit terminated(sigPid, appName); - execute( appName, QString::null ); + qWarning("Re executing obmitted for %s", appName.latin1() ); +// execute( appName, QString::null ); return; } } } #endif - + emit terminated(sigPid, appName); } #else void AppLauncher::sigStopped(int sigPid, int sigStatus) { qDebug("Unhandled signal : AppLauncher::sigStopped(int sigPid, int sigStatus)"); } #endif // Q_OS_WIN32 bool AppLauncher::isRunning(const QString &app) { for (QMap<int,QString>::ConstIterator it = runningApps.begin(); it != runningApps.end(); ++it) { @@ -435,27 +437,27 @@ bool AppLauncher::isRunning(const QString &app) return FALSE; } #endif return TRUE; } } return FALSE; } bool AppLauncher::executeBuiltin(const QString &c, const QString &document) { - Global::Command* builtin = Global::builtinCommands(); - QGuardedPtr<QWidget> *running = Global::builtinRunning(); - + Global::Command* builtin = Opie::Global::builtinCommands(); + QGuardedPtr<QWidget> *running = Opie::Global::builtinRunning(); + // Attempt to execute the app using a builtin class for the app if (builtin) { for (int i = 0; builtin[i].file; i++) { if ( builtin[i].file == c ) { if ( running[i] ) { if ( !document.isNull() && builtin[i].documentary ) Global::setDocument(running[i], document); running[i]->raise(); running[i]->show(); running[i]->setActiveWindow(); } else { running[i] = builtin[i].func( builtin[i].maximized ); @@ -474,70 +476,71 @@ bool AppLauncher::executeBuiltin(const QString &c, const QString &document) QString ap=list[0]; if ( ap == "suspend" ) { // No tr QWSServer::processKeyEvent( 0xffff, Qt::Key_F34, FALSE, TRUE, FALSE ); return TRUE; } return FALSE; } bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRaise) { + qWarning("AppLauncher::execute"); // Convert the command line in to a list of arguments QStringList list = QStringList::split(QRegExp(" *"),c); if ( !docParam.isEmpty() ) list.append( docParam ); QString appName = list[0]; if ( isRunning(appName) ) { QCString channel = "QPE/Application/"; channel += appName.latin1(); - + // Need to lock it to avoid race conditions with QPEApplication::processQCopFile - QFile f(Global::tempDir() + "qcop-msg-" + appName); + QFile f(Opie::Global::tempDir() + "qcop-msg-" + appName); if ( !noRaise && f.open(IO_WriteOnly | IO_Append) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif - + QDataStream ds(&f); QByteArray b; QDataStream bstream(b, IO_WriteOnly); if ( !f.size() ) { ds << channel << QCString("raise()") << b; if ( !waitingHeartbeat.contains( appName ) && appKillerName != appName ) { int id = startTimer(RAISE_TIMEOUT_MS); waitingHeartbeat.insert( appName, id ); } } if ( !docParam.isEmpty() ) { bstream << docParam; ds << channel << QCString("setDocument(QString)") << b; } f.flush(); #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_UN); #endif f.close(); } if ( QCopChannel::isRegistered(channel) ) // avoid unnecessary warnings QCopChannel::send(channel,"QPEProcessQCop()"); - + return TRUE; } #ifdef QT_NO_QWS_MULTIPROCESS - QMessageBox::warning( 0, tr("Error"), tr("Could not find the application %1").arg(c), + QMessageBox::warning( 0, tr("Error"), tr("<qt>Could not find the application %1</qt>").arg(c), tr("OK"), 0, 0, 0, 1 ); #else QStrList slist; unsigned j; for ( j = 0; j < list.count(); j++ ) slist.append( list[j].utf8() ); const char **args = new const char *[slist.count() + 1]; for ( j = 0; j < slist.count(); j++ ) args[j] = slist.at(j); args[j] = NULL; @@ -576,25 +579,25 @@ bool AppLauncher::execute(const QString &c, const QString &docParam, bool noRais #else QProcess *proc = new QProcess(this); if (proc){ for (int i=0; i < slist.count(); i++) proc->addArgument(args[i]); connect(proc, SIGNAL(processExited()), this, SLOT(processExited())); if (!proc->start()){ qDebug("Unable to start application %s", args[0]); }else{ PROCESS_INFORMATION *procInfo = (PROCESS_INFORMATION *)proc->processIdentifier(); if (procInfo){ DWORD pid = procInfo->dwProcessId; - runningApps[pid] = QString(args[0]); + runningApps[pid] = QString(args[0]); runningAppsProc.append(proc); emit launched(pid, QString(args[0])); QCopEnvelope e("QPE/System", "busy()"); }else{ qDebug("Unable to read process inforation #1 for %s", args[0]); } } }else{ qDebug("Unable to create process for application %s", args[0]); return FALSE; } #endif @@ -626,61 +629,67 @@ int AppLauncher::pidForName( const QString &appName ) for (it = runningApps.begin(); it!= runningApps.end(); ++it) { if (*it == appName) { pid = it.key(); break; } } return pid; } void AppLauncher::createQuickLauncher() { + static bool disabled = FALSE; + if (disabled) + return; + qlReady = FALSE; qlPid = ::vfork(); if ( !qlPid ) { char **args = new char *[2]; args[0] = "quicklauncher"; args[1] = 0; for ( int fd = 3; fd < 100; fd++ ) ::close( fd ); ::setpgid( ::getpid(), ::getppid() ); // Try bindir first, so that foo/bar works too setenv( "LD_BIND_NOW", "1", 1 ); ::execv( QPEApplication::qpeDir()+"bin/quicklauncher", args ); ::execvp( "quicklauncher", args ); + delete []args; + disabled = TRUE; _exit( -1 ); } else if ( qlPid == -1 ) { qlPid = 0; } else { if ( getuid() == 0 ) setpriority( PRIO_PROCESS, qlPid, 19 ); } } // Used only by Win32 void AppLauncher::processExited() { #ifdef Q_OS_WIN32 qDebug("AppLauncher::processExited()"); bool found = FALSE; QProcess *proc = (QProcess *) sender(); if (!proc){ qDebug("Interanl error NULL proc"); return; } QString appName = proc->arguments()[0]; qDebug("Removing application %s", appName.latin1()); - runningAppsProc.remove(proc); + runningAppsProc.remove(proc); QMap<QString,int>::Iterator hbit = waitingHeartbeat.find(appName); if ( hbit != waitingHeartbeat.end() ) { killTimer( *hbit ); waitingHeartbeat.remove( hbit ); } if ( appName == appKillerName ) { appKillerName = QString::null; delete appKillerBox; appKillerBox = 0; } @@ -690,16 +699,16 @@ void AppLauncher::processExited() if (it.data() == appName){ found = TRUE; break; } } if (found){ emit terminated(it.key(), it.data()); runningApps.remove(it.key()); }else{ qDebug("Internal error application %s not listed as running", appName.latin1()); } - + #endif } |