io/process: mask the "QProcess destroyed for running process" warn

This commit is contained in:
outfoxxed 2025-07-02 20:16:47 -07:00
parent f681e2016f
commit 86591f122d
Signed by untrusted user: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 88 additions and 3 deletions

View file

@ -27,6 +27,21 @@ Process::Process(QObject* parent): QObject(parent) {
);
}
Process::~Process() {
if (this->process != nullptr && this->process->processId() != 0) {
// Deleting after the process finishes hides the process destroyed warning in logs
QObject::connect(this->process, &QProcess::finished, [p = this->process] { delete p; });
this->process->setParent(nullptr);
this->process->kill();
}
}
void Process::onPostReload() {
this->postReload = true;
this->startProcessIfReady();
}
bool Process::isRunning() const { return this->process != nullptr; }
void Process::setRunning(bool running) {
@ -165,7 +180,9 @@ void Process::setStdinEnabled(bool enabled) {
}
void Process::startProcessIfReady() {
if (this->process != nullptr || !this->targetRunning || this->mCommand.isEmpty()) return;
if (this->process != nullptr || !this->postReload || !this->targetRunning
|| this->mCommand.isEmpty())
return;
this->targetRunning = false;
auto& cmd = this->mCommand.first();

View file

@ -11,6 +11,7 @@
#include <qvariant.h>
#include "../core/doc.hpp"
#include "../core/reload.hpp"
#include "datastream.hpp"
#include "processcore.hpp"
@ -30,7 +31,9 @@
/// }
/// }
/// ```
class Process: public QObject {
class Process
: public QObject
, public PostReloadHook {
Q_OBJECT;
// clang-format off
/// If the process is currently running. Defaults to false.
@ -136,6 +139,10 @@ class Process: public QObject {
public:
explicit Process(QObject* parent = nullptr);
~Process() override;
Q_DISABLE_COPY_MOVE(Process);
void onPostReload() override;
// MUST be before exec(ctx) or the other will be called with a default constructed obj.
QSDOC_HIDE Q_INVOKABLE void exec(QList<QString> command);
@ -251,4 +258,5 @@ private:
bool targetRunning = false;
bool mStdinEnabled = false;
bool mClearEnvironment = false;
bool postReload = false;
};

View file

@ -1,7 +1,8 @@
function (qs_test name)
add_executable(${name} ${ARGN})
target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test quickshell-io)
target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test quickshell-io quickshell-core quickshell-window quickshell-ui)
add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
endfunction()
qs_test(datastream datastream.cpp ../datastream.cpp)
qs_test(process process.cpp ../process.cpp ../datastream.cpp ../processcore.cpp)

47
src/io/test/process.cpp Normal file
View file

@ -0,0 +1,47 @@
#include "process.hpp"
#include <qlist.h>
#include <qsignalspy.h>
#include <qtest.h>
#include <qtestcase.h>
#include "../process.hpp"
void TestProcess::startAfterReload() {
auto process = Process();
auto startedSpy = QSignalSpy(&process, &Process::started);
auto exitedSpy = QSignalSpy(&process, &Process::exited);
process.setCommand({"true"});
process.setRunning(true);
QVERIFY(!process.isRunning());
QCOMPARE(startedSpy.count(), 0);
process.onPostReload();
QVERIFY(process.isRunning());
QVERIFY(startedSpy.wait(100));
}
void TestProcess::testExec() {
auto process = Process();
auto startedSpy = QSignalSpy(&process, &Process::started);
auto exitedSpy = QSignalSpy(&process, &Process::exited);
process.onPostReload();
process.setCommand({"sleep", "30"});
process.setRunning(true);
QVERIFY(process.isRunning());
QVERIFY(startedSpy.wait(100));
process.exec({"true"});
QVERIFY(exitedSpy.wait(100));
QVERIFY(startedSpy.wait(100));
QVERIFY(process.isRunning());
}
QTEST_MAIN(TestProcess);

12
src/io/test/process.hpp Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include <qobject.h>
#include <qtmetamacros.h>
class TestProcess: public QObject {
Q_OBJECT;
private slots:
static void startAfterReload();
static void testExec();
};