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 2c50bed1d8
commit 5a2f75dd0d
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();
{
std::scoped_lock<std::mutex> lock(configMutex);
if (!RuntimeConfig::Get().hasPackagesScript) if (!RuntimeConfig::Get().hasPackagesScript)
{ {
configMutex.unlock();
return; // Don't bother return; // Don't bother
} }
configMutex.unlock(); handlerFunction = returnVal;
if (currentlyRunning)
{
// Thread is running, only update handler
return;
}
currentlyRunning = true;
}
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;
{
std::scoped_lock<std::mutex> lock(configMutex);
if (exitCode != 0) if (exitCode != 0)
{ {
configMutex.lock();
// Invalid script/error // Invalid script/error
LOG("GetOutdatedPackages: Invalid command. Disabling package widget!"); LOG("GetOutdatedPackages: Invalid command. Disabling package widget!");
RuntimeConfig::Get().hasPackagesScript = false; RuntimeConfig::Get().hasPackagesScript = false;
configMutex.unlock(); currentlyRunning = false;
return; return;
} }
try try
{ {
returnVal(std::stoul(buf)); handlerFunction(std::stoul(buf));
} }
catch (std::invalid_argument&) catch (std::invalid_argument&)
{ {
configMutex.lock();
LOG("GetOutdatedPackages: Invalid output of the package script. Disabling package widget!"); LOG("GetOutdatedPackages: Invalid output of the package script. Disabling package widget!");
RuntimeConfig::Get().hasPackagesScript = false; RuntimeConfig::Get().hasPackagesScript = false;
configMutex.unlock();
return;
} }
}, currentlyRunning = false;
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();