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 /*! Utility function to execute a command on the local machine. Used
* to restart applications. * to restart applications.
*/ */
QProcess* KSMServer::startApplication( const QStringList& cmd, const QString& clientMachine, bool KSMServer::startApplication( const QStringList& cmd, const QString& clientMachine,
const QString& userId, bool wm ) const QString& userId )
{ {
QStringList command = cmd; QStringList command = cmd;
if ( command.isEmpty() ) if ( command.isEmpty() )
return NULL; return false;
if ( !userId.isEmpty()) { if ( !userId.isEmpty()) {
const KUser kuser(::getuid()); const KUser kuser(::getuid());
if( kuser.isValid() && userId != kuser.loginName() ) { 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 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 int n = command.count();
// or not, so this should be redone. For now, use QProcess for wm's, as they need to be tracked, org::kde::KLauncher klauncher("org.kde.klauncher", "/KLauncher", QDBusConnection::sessionBus());
// klauncher for the rest where ksmserver doesn't care. QString app = command[0];
if( wm ) { QStringList argList;
QProcess* process = new QProcess( this ); for ( int i=1; i < n; i++)
QString program = command.takeAt(0); argList.append( command[i]);
// make it auto-delete klauncher.exec_blind(app, argList );
connect( process, SIGNAL(error(QProcess::ProcessError)), process, SLOT(deleteLater())); return true;
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;
}
} }
/*! Utility function to execute a command on the local machine. Used /*! Utility function to execute a command on the local machine. Used

View file

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