Commit 3ddbc351 authored by Stefan Brüns's avatar Stefan Brüns
Browse files

Avoid double free/use-after-free of static unique_ptr<>

The processtest autotest crashes as the static ProcessLocal is apparently
destructed twice from the global destructor list on program exit. The
issue can be triggered even with a trivial program:

```
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    KSysGuardProcessList processList;
}
```
parent 9c17f75e
find_package(Qt5 REQUIRED CONFIG COMPONENTS Test)
include_directories(${libksysguard_SOURCE_DIR})
if(Qt5WebEngineWidgets_FOUND)
# Process unit test
ecm_qt_declare_logging_category(processtest_debug_SRCS HEADER processcore_debug.h IDENTIFIER LIBKSYSGUARD_PROCESSCORE CATEGORY_NAME org.kde.libksysguard.processcore)
ecm_add_test(processtest.cpp ${processtest_debug_SRCS} TEST_NAME processtest
LINK_LIBRARIES KSysGuard::ProcessUi Qt5::Test)
endif()
# Process unit test
ecm_qt_declare_logging_category(processtest_debug_SRCS HEADER processcore_debug.h IDENTIFIER LIBKSYSGUARD_PROCESSCORE CATEGORY_NAME org.kde.libksysguard.processcore)
ecm_add_test(processtest.cpp ${processtest_debug_SRCS} TEST_NAME processtest
LINK_LIBRARIES KSysGuard::ProcessUi Qt5::Test)
if (KF5Plasma_FOUND)
set(SIGNALPLOTTER_DEBUG_SRCS)
......
......@@ -47,21 +47,16 @@ public:
QVector<int> listToVector(const QVariantList &list);
QWidget *widget;
// Note: This instance is only to have access to the platform-specific code
// for sending signals, setting priority etc. Therefore, it should never be
// used to access information about processes.
static std::unique_ptr<ProcessesLocal> localProcesses;
};
std::unique_ptr<ProcessesLocal> ProcessController::Private::localProcesses;
// Note: This instance is only to have access to the platform-specific code
// for sending signals, setting priority etc. Therefore, it should never be
// used to access information about processes.
Q_GLOBAL_STATIC(ProcessesLocal, s_localProcesses);
ProcessController::ProcessController(QObject* parent)
: QObject(parent), d(new Private)
{
if (!d->localProcesses) {
d->localProcesses = std::make_unique<ProcessesLocal>();
}
}
KSysGuard::ProcessController::~ProcessController()
......@@ -83,7 +78,7 @@ ProcessController::Result ProcessController::sendSignal(const QVector<int>& pids
{
qCDebug(LIBKSYSGUARD_PROCESSCORE) << "Sending signal" << signal << "to" << pids;
auto result = d->applyToPids(pids, [this, signal](int pid) { return d->localProcesses->sendSignal(pid, signal); });
auto result = d->applyToPids(pids, [this, signal](int pid) { return s_localProcesses->sendSignal(pid, signal); });
if (result.unchanged.isEmpty()) {
return result.resultCode;
}
......@@ -107,7 +102,7 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::sendSignal(co
ProcessController::Result ProcessController::setPriority(const QVector<int>& pids, int priority)
{
auto result = d->applyToPids(pids, [this, priority](int pid) { return d->localProcesses->setNiceness(pid, priority); });
auto result = d->applyToPids(pids, [this, priority](int pid) { return s_localProcesses->setNiceness(pid, priority); });
if (result.unchanged.isEmpty()) {
return result.resultCode;
}
......@@ -136,7 +131,7 @@ ProcessController::Result ProcessController::setCPUScheduler(const QVector<int>&
}
auto result = d->applyToPids(pids, [this, scheduler, priority](int pid) {
return d->localProcesses->setScheduler(pid, scheduler, priority);
return s_localProcesses->setScheduler(pid, scheduler, priority);
});
if (result.unchanged.isEmpty()) {
return result.resultCode;
......@@ -161,7 +156,7 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::setCPUSchedul
ProcessController::Result ProcessController::setIOScheduler(const QVector<int>& pids, Process::IoPriorityClass priorityClass, int priority)
{
if (!d->localProcesses->supportsIoNiceness()) {
if (!s_localProcesses->supportsIoNiceness()) {
return Result::Unsupported;
}
......@@ -174,7 +169,7 @@ ProcessController::Result ProcessController::setIOScheduler(const QVector<int>&
}
auto result = d->applyToPids(pids, [this, priorityClass, priority](int pid) {
return d->localProcesses->setIoNiceness(pid, priorityClass, priority);
return s_localProcesses->setIoNiceness(pid, priorityClass, priority);
});
if (result.unchanged.isEmpty()) {
return result.resultCode;
......@@ -221,12 +216,12 @@ ApplyResult KSysGuard::ProcessController::Private::applyToPids(const QVector<int
{
ApplyResult result;
localProcesses->errorCode = KSysGuard::Processes::Unknown;
s_localProcesses->errorCode = KSysGuard::Processes::Unknown;
for (auto pid : pids) {
auto success = function(pid);
if (!success) {
switch (localProcesses->errorCode) {
switch (s_localProcesses->errorCode) {
case KSysGuard::Processes::InsufficientPermissions:
case KSysGuard::Processes::Unknown:
result.unchanged << pid;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment