io/process!: replace manageLifetime with startDetached

In most cases this is what was desired for usages of
manageLifetime. Starting the process in a detached state also makes
sure the process hierarchy will not result in the child being killed when
Quickshell is killed.
This commit is contained in:
outfoxxed 2025-03-12 00:53:36 -07:00
parent c5bea858a0
commit 0662c37d67
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
5 changed files with 37 additions and 76 deletions

View file

@ -8,6 +8,7 @@
#include <qmap.h>
#include <qobject.h>
#include <qprocess.h>
#include <qqmlinfo.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qvariant.h>
@ -16,10 +17,6 @@
#include "../core/qmlglobal.hpp"
#include "datastream.hpp"
// When the process ends this have no parent and is just leaked,
// meaning the destructor never runs and they are never killed.
static DisownedProcessContext* disownedCtx; // NOLINT
Process::Process(QObject* parent): QObject(parent) {
QObject::connect(
QuickshellSettings::instance(),
@ -29,13 +26,6 @@ Process::Process(QObject* parent): QObject(parent) {
);
}
Process::~Process() {
if (!this->mLifetimeManaged && this->process != nullptr) {
if (disownedCtx == nullptr) disownedCtx = new DisownedProcessContext(); // NOLINT
disownedCtx->reparent(this->process);
}
}
bool Process::isRunning() const { return this->process != nullptr; }
void Process::setRunning(bool running) {
@ -183,14 +173,6 @@ void Process::setStdinEnabled(bool enabled) {
emit this->stdinEnabledChanged();
}
bool Process::isLifetimeManaged() const { return this->mLifetimeManaged; }
void Process::setLifetimeManaged(bool managed) {
if (managed == this->mLifetimeManaged) return;
this->mLifetimeManaged = managed;
emit this->lifetimeManagedChanged();
}
void Process::startProcessIfReady() {
if (this->process != nullptr || !this->targetRunning || this->mCommand.isEmpty()) return;
this->targetRunning = false;
@ -215,8 +197,30 @@ void Process::startProcessIfReady() {
if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError);
if (!this->mStdinEnabled) this->process->closeWriteChannel();
this->setupEnvironment(this->process);
this->process->start(cmd, args);
}
void Process::startDetached() {
if (this->mCommand.isEmpty()) {
qmlWarning(this) << "Cannot start process as command is empty.";
return;
}
auto& cmd = this->mCommand.first();
auto args = this->mCommand.sliced(1);
QProcess process;
this->setupEnvironment(&process);
process.setProgram(cmd);
process.setArguments(args);
process.startDetached();
}
void Process::setupEnvironment(QProcess* process) {
if (!this->mWorkingDirectory.isEmpty()) {
this->process->setWorkingDirectory(this->mWorkingDirectory);
process->setWorkingDirectory(this->mWorkingDirectory);
}
if (!this->mEnvironment.isEmpty() || this->mClearEnvironment) {
@ -237,10 +241,8 @@ void Process::startProcessIfReady() {
}
}
this->process->setProcessEnvironment(env);
process->setProcessEnvironment(env);
}
this->process->start(cmd, args);
}
void Process::onStarted() {
@ -291,13 +293,3 @@ void Process::write(const QString& data) {
if (this->process == nullptr) return;
this->process->write(data.toUtf8());
}
void DisownedProcessContext::reparent(QProcess* process) {
process->setParent(this);
QObject::connect(process, &QProcess::finished, this, [process]() { process->deleteLater(); });
}
void DisownedProcessContext::destroyInstance() {
delete disownedCtx;
disownedCtx = nullptr;
}