From 31777a980e0f4b1b258713158524c0cd9a1dc30f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 18 Oct 2019 19:33:20 +0200 Subject: Use execv() to start selected session Prevent vmchooser from lingering in the background, like a zombie, haunting you with invisible windows. Also seems to be notably faster when launching the openbox session. --- src/dialog.cpp | 91 +++++++++++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 55 deletions(-) (limited to 'src/dialog.cpp') diff --git a/src/dialog.cpp b/src/dialog.cpp index 914448f..dbc4b8e 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -136,9 +136,11 @@ void Dialog::on_treeView_doubleClicked(const QModelIndex& index) return; // Check preconditions. The method might show error messages and return false - if (!s->canRun(true)) + if (!s->prepareRun()) return; + WindowManager::stopOwnInstance(true); + // These two are up here in case run-virt cares... if (Config::isSet(Config::PVS)) { if (ui->PVS_checkbox->isChecked()) { @@ -159,62 +161,41 @@ void Dialog::on_treeView_doubleClicked(const QModelIndex& index) setenv("VMCHOOSER_DISABLE_SCREENSAVER", "FALSE", 1); } - // Run session - if (s->run()) { - // Run session start script if the session could be initialized successfully - if (QFile::exists(SESSION_START_SCRIPT)) { - // Use the current environment variables and add the necessary - // information for the startUpScipt. - // export session information to the environment of the process to be exec'ed - setenv("SESSION_NAME", s->shortDescription().toUtf8(), 1); - setenv("SESSION_UUID", s->uuid().toUtf8(), 1); - setenv("SESSION_CMD", s->execCommand().toUtf8(), 1); - if (s->type() == Session::VSESSION) { - setenv("SESSION_TYPE", "VSESSION", 1); - } else if (s->type() == Session::XSESSION) { - setenv("SESSION_TYPE", "XSESSION", 1); - } - // Fork this process twice to detach - pid_t pid = fork(); - if (pid == 0) { - - // Close all filedescriptors - for (int i = 3; i < 1024; ++i) - ::close(i); - - // Change process group - setsid(); - - // Reopen standard pipes - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); - - pid = fork(); - if (pid == 0) { - // At this point we are executing as the 2nd child process - // Replace this clone with the process we'd like to start - char * const args[] = { strdup(VMCHOOSER_SESSION_START_SCRIPT), nullptr }; - execv(VMCHOOSER_SESSION_START_SCRIPT, args); - } - _exit(0); // Dont use exit hooks - } - // Wait and cleanup the intermediate process - waitpid(pid, nullptr, 0); + UserConfig::addLastSession(s->uuid().isEmpty() ? s->shortDescription() : s->uuid()); + UserConfig::setLastTab(activeTab_); + UserConfig::setNewsHelpOpen(!ui->helpBox->isHidden()); + UserConfig::sync(); + + QProcess *process = nullptr; + if (QFile::exists(SESSION_START_SCRIPT)) { + // Companion script + process = new QProcess; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("SESSION_NAME", s->shortDescription()); + env.insert("SESSION_UUID", s->uuid()); + env.insert("SESSION_CMD", s->execCommand()); + if (s->type() == Session::VSESSION) { + env.insert("SESSION_TYPE", "VSESSION"); + } else if (s->type() == Session::XSESSION) { + env.insert("SESSION_TYPE", "XSESSION"); } - UserConfig::addLastSession(s->uuid().isEmpty() ? s->shortDescription() : s->uuid()); - UserConfig::setLastTab(activeTab_); - UserConfig::setNewsHelpOpen(!ui->helpBox->isHidden()); - centerTimer_->stop(); // Stop the auto-center/auto-quit timer, so we don't kill the session :> - setVisible(false); - // Stopping the window manager has to be done after hiding our window, - // or it might still be shown in some Xsessions (e.g. gnome-shell). - WindowManager::stopOwnInstance(); - } else { - QMessageBox::critical( - this, trUtf8("vmchooser"), - trUtf8("Vmchooser failed to run the selected session!")); + process->setProcessEnvironment(env); + process->start(SESSION_START_SCRIPT); + process->closeReadChannel(QProcess::StandardError); + process->closeReadChannel(QProcess::StandardOutput); + process->closeWriteChannel(); } + + // Run session + s->run(); + // Should not return on success + if (process != nullptr) { + process->terminate(); + } + QMessageBox::critical( + this, trUtf8("vmchooser"), + trUtf8("Vmchooser failed to run the selected session!")); + QApplication::instance()->quit(); } void Dialog::on_treeView_expanded(const QModelIndex& index) { -- cgit v1.2.3-55-g7522