Changeset View
Changeset View
Standalone View
Standalone View
startkde/plasma-session/startup.cpp
Show First 20 Lines • Show All 197 Lines • ▼ Show 20 Line(s) | |||||
198 | 198 | | |||
199 | Startup::Startup(QObject *parent): | 199 | Startup::Startup(QObject *parent): | ||
200 | QObject(parent) | 200 | QObject(parent) | ||
201 | { | 201 | { | ||
202 | new StartupAdaptor(this); | 202 | new StartupAdaptor(this); | ||
203 | QDBusConnection::sessionBus().registerObject(QStringLiteral("/Startup"), QStringLiteral("org.kde.Startup"), this); | 203 | QDBusConnection::sessionBus().registerObject(QStringLiteral("/Startup"), QStringLiteral("org.kde.Startup"), this); | ||
204 | QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Startup")); | 204 | QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Startup")); | ||
205 | 205 | | |||
206 | upAndRunning(QStringLiteral("ksmserver")); | ||||
206 | const AutoStart autostart; | 207 | const AutoStart autostart; | ||
207 | 208 | | |||
208 | auto phase0 = new StartupPhase0(autostart, this); | 209 | KJob* phase1; | ||
209 | auto phase1 = new StartupPhase1(autostart, this); | 210 | QProcessEnvironment kdedProcessEnv; | ||
210 | auto phase2 = new StartupPhase2(autostart, this); | 211 | kdedProcessEnv.insert(QStringLiteral("KDED_STARTED_BY_KDEINIT"), QStringLiteral("1")); | ||
fvogt: This (and below) are started with an empty environment, which means that neither `DISPLAY`… | |||||
StartProcessJob I think is fine. It's not set, so it'll inherit. It's the extra arg to StartServiceJob that has potential to wipe the env. It defaults to empty and we do p->setEnvironment(m_env); davidedmundson: StartProcessJob I think is fine. It's not set, so it'll inherit.
It's the extra arg to… | |||||
It is set in line 440, which defaults to empty (line 90 in the header) as well. fvogt: > StartProcessJob I think is fine. It's not set, so it'll inherit.
It is set in line 440… | |||||
211 | auto restoreSession = new RestoreSessionJob(); | 212 | | ||
212 | 213 | const QVector<KJob*> sequence = { | |||
213 | // this includes starting kwin (currently) | 214 | new StartProcessJob(QStringLiteral("kcminit_startup"), {}), | ||
214 | // forward our arguments into ksmserver to match startplasma expectations | 215 | new StartServiceJob(QStringLiteral("kded5"), {}, QStringLiteral("org.kde.kded5"), kdedProcessEnv), | ||
215 | QStringList arguments = qApp->arguments(); | 216 | new StartServiceJob(QStringLiteral("ksmserver"), QCoreApplication::instance()->arguments().mid(1), QStringLiteral("org.kde.ksmserver")), | ||
216 | arguments.removeFirst(); | 217 | new StartupPhase0(autostart, this), | ||
217 | auto ksmserverJob = new StartServiceJob(QStringLiteral("ksmserver"), arguments, QStringLiteral("org.kde.ksmserver")); | 218 | phase1 = new StartupPhase1(autostart, this), | ||
218 | 219 | new RestoreSessionJob(), | |||
219 | connect(ksmserverJob, &KJob::finished, phase0, &KJob::start); | 220 | new StartupPhase2(autostart, this), | ||
220 | 221 | }; | |||
221 | connect(phase0, &KJob::finished, phase1, &KJob::start); | 222 | KJob* last = nullptr; | ||
222 | 223 | for(KJob* job : sequence) { | |||
223 | connect(phase1, &KJob::finished, restoreSession, &KJob::start); | 224 | if (last) { | ||
224 | connect(restoreSession, &KJob::finished, phase2, &KJob::start); | 225 | connect(last, &KJob::finished, job, &KJob::start); | ||
225 | upAndRunning(QStringLiteral("ksmserver")); | 226 | } | ||
227 | last = job; | ||||
228 | } | ||||
226 | 229 | | |||
227 | connect(phase1, &KJob::finished, this, []() { | 230 | connect(phase1, &KJob::finished, this, []() { | ||
228 | NotificationThread *loginSound = new NotificationThread(); | 231 | NotificationThread *loginSound = new NotificationThread(); | ||
229 | connect(loginSound, &NotificationThread::finished, loginSound, &NotificationThread::deleteLater); | 232 | connect(loginSound, &NotificationThread::finished, loginSound, &NotificationThread::deleteLater); | ||
230 | loginSound->start();}); | 233 | loginSound->start();}); | ||
231 | connect(phase2, &KJob::finished, this, &Startup::finishStartup); | | |||
232 | 234 | | |||
apol: Unrelated change. | |||||
233 | ksmserverJob->start(); | 235 | connect(sequence.last(), &KJob::finished, this, &Startup::finishStartup); | ||
236 | sequence.first()->start(); | ||||
234 | } | 237 | } | ||
235 | 238 | | |||
236 | void Startup::upAndRunning( const QString& msg ) | 239 | void Startup::upAndRunning( const QString& msg ) | ||
237 | { | 240 | { | ||
238 | QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), | 241 | QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), | ||
239 | QStringLiteral("/KSplash"), | 242 | QStringLiteral("/KSplash"), | ||
240 | QStringLiteral("org.kde.KSplash"), | 243 | QStringLiteral("org.kde.KSplash"), | ||
241 | QStringLiteral("setStage")); | 244 | QStringLiteral("setStage")); | ||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Line(s) | 389 | do { | |||
403 | auto program = arguments.takeFirst(); | 406 | auto program = arguments.takeFirst(); | ||
404 | if (!QProcess::startDetached(program, arguments)) | 407 | if (!QProcess::startDetached(program, arguments)) | ||
405 | qCWarning(PLASMA_SESSION) << "could not start" << serviceName << ":" << program << arguments; | 408 | qCWarning(PLASMA_SESSION) << "could not start" << serviceName << ":" << program << arguments; | ||
406 | } while (true); | 409 | } while (true); | ||
407 | }); | 410 | }); | ||
408 | } | 411 | } | ||
409 | 412 | | |||
410 | 413 | | |||
411 | StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId): | 414 | | ||
412 | KJob(), | 415 | StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId, const QProcessEnvironment &additionalEnv) | ||
413 | m_process(process), | 416 | : KJob() | ||
414 | m_args(args), | 417 | , m_process(new QProcess(this)) | ||
415 | m_serviceId(serviceId) | 418 | , m_serviceId(serviceId) | ||
416 | { | 419 | { | ||
420 | m_process->setProgram(process); | ||||
421 | m_process->setArguments(args); | ||||
422 | auto env = QProcessEnvironment::systemEnvironment(); | ||||
Maybe it would make sense to do the merging of envs here? This way we only set when it's necessary. apol: Maybe it would make sense to do the merging of envs here? This way we only set when it's… | |||||
apol: only do it `if (!additionalEnv.isEmpty())` | |||||
423 | env.insert(additionalEnv); | ||||
424 | m_process->setProcessEnvironment(env); | ||||
425 | | ||||
417 | auto watcher = new QDBusServiceWatcher(serviceId, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); | 426 | auto watcher = new QDBusServiceWatcher(serviceId, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); | ||
418 | connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &StartServiceJob::emitResult); | 427 | connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &StartServiceJob::emitResult); | ||
419 | } | 428 | } | ||
420 | 429 | | |||
421 | void StartServiceJob::start() | 430 | void StartServiceJob::start() | ||
422 | { | 431 | { | ||
423 | if (QDBusConnection::sessionBus().interface()->isServiceRegistered(m_serviceId)) { | 432 | if (QDBusConnection::sessionBus().interface()->isServiceRegistered(m_serviceId)) { | ||
424 | qCDebug(PLASMA_SESSION) << m_process << "already running"; | 433 | qCDebug(PLASMA_SESSION) << m_process << "already running"; | ||
425 | emitResult(); | 434 | emitResult(); | ||
426 | return; | 435 | return; | ||
427 | } | 436 | } | ||
428 | qCDebug(PLASMA_SESSION) << "Starting " << m_process << m_args; | 437 | qCDebug(PLASMA_SESSION) << "Starting " << m_process->program() << m_process->arguments(); | ||
429 | QProcess::startDetached(m_process, m_args); | 438 | if (!m_process->startDetached()) { | ||
439 | qCWarning(PLASMA_SESSION) << "error starting process" << m_process->program() << m_process->arguments(); | ||||
440 | emitResult(); | ||||
430 | } | 441 | } | ||
442 | } | ||||
443 | | ||||
444 | StartProcessJob::StartProcessJob(const QString &process, const QStringList &args, const QProcessEnvironment &additionalEnv) | ||||
445 | : KJob() | ||||
446 | , m_process(new QProcess(this)) | ||||
447 | { | ||||
448 | m_process->setProgram(process); | ||||
449 | m_process->setArguments(args); | ||||
450 | auto env = QProcessEnvironment::systemEnvironment(); | ||||
apol: only do it if (!additionalEnv.isEmpty())
| |||||
451 | env.insert(additionalEnv); | ||||
452 | m_process->setProcessEnvironment(env); | ||||
431 | 453 | | |||
454 | connect(m_process, static_cast<void (QProcess::*)(int)>(&QProcess::finished), [this](int exitCode) { | ||||
455 | qCInfo(PLASMA_SESSION) << "process job " << m_process->program() << "finished with exit code " << exitCode; | ||||
456 | emitResult(); | ||||
457 | }); | ||||
458 | } | ||||
459 | | ||||
460 | void StartProcessJob::start() | ||||
461 | { | ||||
462 | qCDebug(PLASMA_SESSION) << "Starting " << m_process->program() << m_process->arguments(); | ||||
463 | | ||||
464 | m_process->start(); | ||||
465 | } | ||||
432 | 466 | | |||
433 | #include "startup.moc" | 467 | #include "startup.moc" |
This (and below) are started with an empty environment, which means that neither DISPLAY, WAYLAND_DISPLAY or XAUTHORITY are set. So everything breaks horribly, as seen by @lbeltrame and openQA.