ksmserver: move process launching code to startup source file

note that connecting to signals after the process is started (which is also
auto-deleted) as was done in KSMServer::launchWM() could result in a race

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-11-15 01:28:27 +02:00
parent 14d80d413b
commit 7fc137c6f2
3 changed files with 26 additions and 36 deletions

View file

@ -91,12 +91,12 @@ KSMServer* KSMServer::self()
/*! Utility function to execute a command on the local machine. Used
* to restart applications.
*/
QProcess* KSMServer::startApplication( const QStringList& cmd, const QString& clientMachine,
const QString& userId, bool wm )
bool KSMServer::startApplication( const QStringList& cmd, const QString& clientMachine,
const QString& userId )
{
QStringList command = cmd;
if ( command.isEmpty() )
return NULL;
return false;
if ( !userId.isEmpty()) {
const KUser kuser(::getuid());
if( kuser.isValid() && userId != kuser.loginName() ) {
@ -111,28 +111,15 @@ QProcess* KSMServer::startApplication( const QStringList& cmd, const QString& cl
command.prepend( xonCommand ); // "xon" by default
}
// TODO this function actually should not use QProcess at all and use klauncher (kdeinit) instead.
// Klauncher should also have support for tracking whether the launched process is still alive
// or not, so this should be redone. For now, use QProcess for wm's, as they need to be tracked,
// klauncher for the rest where ksmserver doesn't care.
if( wm ) {
QProcess* process = new QProcess( this );
QString program = command.takeAt(0);
// make it auto-delete
connect( process, SIGNAL(error(QProcess::ProcessError)), process, SLOT(deleteLater()));
connect( process, SIGNAL(finished(int,QProcess::ExitStatus)), process, SLOT(deleteLater()));
process->start(program, command);
return process;
} else {
int n = command.count();
org::kde::KLauncher klauncher("org.kde.klauncher", "/KLauncher", QDBusConnection::sessionBus());
QString app = command[0];
QStringList argList;
for ( int i=1; i < n; i++)
argList.append( command[i]);
klauncher.exec_blind(app, argList );
return NULL;
}
int n = command.count();
org::kde::KLauncher klauncher("org.kde.klauncher", "/KLauncher", QDBusConnection::sessionBus());
QString app = command[0];
QStringList argList;
for ( int i=1; i < n; i++)
argList.append( command[i]);
klauncher.exec_blind(app, argList );
return true;
}
/*! Utility function to execute a command on the local machine. Used

View file

@ -166,10 +166,9 @@ private:
void startProtection();
void endProtection();
QProcess* startApplication( const QStringList& command,
const QString& clientMachine = QString(),
const QString& userId = QString(),
bool wm = false );
bool startApplication( const QStringList& command,
const QString& clientMachine = QString(),
const QString& userId = QString());
void executeCommand( const QStringList& command );
bool isWM( const KSMClient* client ) const;

View file

@ -143,9 +143,12 @@ void KSMServer::launchWM( const QList< QStringList >& wmStartCommands )
// when we have a window manager, we start it first and give
// it some time before launching other processes. Results in a
// visually more appealing startup.
wmProcess = startApplication( wmStartCommands[ 0 ], QString(), QString(), true );
connect( wmProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(wmProcessChange()));
connect( wmProcess, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(wmProcessChange()));
QStringList wmCommand = wmStartCommands[0];
QString program = wmCommand.takeAt(0);
wmProcess = new QProcess( this );
connect( wmProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(wmProcessChange()));
connect( wmProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(wmProcessChange()));
wmProcess->start(program, wmCommand);
wmProcess->waitForStarted(4000);
QMetaObject::invokeMethod(this, "autoStart0", Qt::QueuedConnection);
}
@ -176,13 +179,14 @@ void KSMServer::clientSetProgram( KSMClient* client )
void KSMServer::wmProcessChange()
{
if( state != LaunchingWM )
{ // don't care about the process when not in the wm-launching state anymore
if( state != LaunchingWM ) {
// don't care about the process when not in the wm-launching state anymore
disconnect(wmProcess, 0, this, 0);
wmProcess = NULL;
return;
}
if( wmProcess->state() == QProcess::NotRunning )
{ // wm failed to launch for some reason, go with kwin instead
if( wmProcess && wmProcess->state() == QProcess::NotRunning ) {
// wm failed to launch for some reason, go with kwin instead
kWarning( 1218 ) << "Window manager" << wm << "failed to launch";
if( wm == "kwin" )
return; // uhoh, kwin itself failed