Only allow sequential runs of package checking

If the current monitor would quickly change, GetOutdatedPackagesAsync
would be called while the previous instance is still running, which
caused crashes. Now, GetOutdatedPackagesAsync only uses one
instance/callback a time.
This commit is contained in:
scorpion-26 2024-03-15 19:30:38 +01:00
parent ad91833407
commit 6fc09324ab
2 changed files with 38 additions and 27 deletions

View file

@ -576,17 +576,28 @@ namespace System
void GetOutdatedPackagesAsync(std::function<void(uint32_t)>&& returnVal) void GetOutdatedPackagesAsync(std::function<void(uint32_t)>&& returnVal)
{ {
static bool currentlyRunning = false;
static std::function<void(uint32_t)> handlerFunction;
static std::mutex configMutex; static std::mutex configMutex;
configMutex.lock();
if (!RuntimeConfig::Get().hasPackagesScript)
{ {
configMutex.unlock(); std::scoped_lock<std::mutex> lock(configMutex);
return; // Don't bother if (!RuntimeConfig::Get().hasPackagesScript)
{
return; // Don't bother
}
handlerFunction = returnVal;
if (currentlyRunning)
{
// Thread is running, only update handler
return;
}
currentlyRunning = true;
} }
configMutex.unlock();
std::thread( std::thread(
[](std::function<void(uint32_t)> returnVal) [&]()
{ {
// We need a pipe, since there is no "libpacman". This should only be called every so often anyways // We need a pipe, since there is no "libpacman". This should only be called every so often anyways
std::string number; std::string number;
@ -601,29 +612,28 @@ namespace System
ASSERT(feof(pipe), "GetOutdatedPackages: Cannot read to eof!"); ASSERT(feof(pipe), "GetOutdatedPackages: Cannot read to eof!");
int exitCode = pclose(pipe) / 256; int exitCode = pclose(pipe) / 256;
if (exitCode != 0)
{ {
configMutex.lock(); std::scoped_lock<std::mutex> lock(configMutex);
// Invalid script/error if (exitCode != 0)
LOG("GetOutdatedPackages: Invalid command. Disabling package widget!"); {
RuntimeConfig::Get().hasPackagesScript = false; // Invalid script/error
configMutex.unlock(); LOG("GetOutdatedPackages: Invalid command. Disabling package widget!");
return; RuntimeConfig::Get().hasPackagesScript = false;
currentlyRunning = false;
return;
}
try
{
handlerFunction(std::stoul(buf));
}
catch (std::invalid_argument&)
{
LOG("GetOutdatedPackages: Invalid output of the package script. Disabling package widget!");
RuntimeConfig::Get().hasPackagesScript = false;
}
currentlyRunning = false;
} }
try })
{
returnVal(std::stoul(buf));
}
catch (std::invalid_argument&)
{
configMutex.lock();
LOG("GetOutdatedPackages: Invalid output of the package script. Disabling package widget!");
RuntimeConfig::Get().hasPackagesScript = false;
configMutex.unlock();
return;
}
},
std::move(returnVal))
.detach(); .detach();
} }

View file

@ -108,6 +108,7 @@ namespace System
// Bytes per second download. dx is time since last call. Will always return 0 on first run // Bytes per second download. dx is time since last call. Will always return 0 on first run
double GetNetworkBpsDownload(double dt); double GetNetworkBpsDownload(double dt);
// This can only be called one at a time. If it is already running it is assumed, that the old handler is no longer valid.
void GetOutdatedPackagesAsync(std::function<void(uint32_t)>&& returnVal); void GetOutdatedPackagesAsync(std::function<void(uint32_t)>&& returnVal);
std::string GetTime(); std::string GetTime();