mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-29 08:06:58 +09:00
* Serialize process registry admission with Symfony Lock Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * Fix PDO process lock mode handling Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: run process lock coverage on PHP 8.2 Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix: confirm a pid is still ours before signalling it #7574 added the still-running guard to dsstats but left six byte-identical siblings signalling a pid straight out of the processes table. After a crash or a power loss the row survives, the pid is recycled by an unrelated daemon, and the next start SIGTERMs a stranger. That is issue #7425, still live in rrdcheck, boost, poller_commands, float_rrdfiles, poller_reindex_hosts and rebuild_poller_cache. Wrap each kill in cacti_process_still_running(), matching the dsstats shape, and leave unregister_process() outside the guard so a stale row is still cleaned up. Cover all seven with a test that walks every kill site, so a new variant cannot reintroduce it. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test: assert the guard plainly toContain() takes needles rather than a failure message, so the file name was being asserted as a second required substring and the test always failed. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs(poller): describe required lock parameters --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
72 lines
3.1 KiB
PHP
72 lines
3.1 KiB
PHP
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| |
|
|
| This program is free software; you can redistribute it and/or |
|
|
| modify it under the terms of the GNU General Public License |
|
|
| as published by the Free Software Foundation; either version 2 |
|
|
| of the License, or (at your option) any later version. |
|
|
| |
|
|
| This program is distributed in the hope that it will be useful, |
|
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
| GNU General Public License for more details. |
|
|
+-------------------------------------------------------------------------+
|
|
| Cacti: The Complete RRDtool-based Graphing Solution |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
use Symfony\Component\Lock\LockFactory;
|
|
use Symfony\Component\Lock\Store\InMemoryStore;
|
|
|
|
require_once dirname(__DIR__, 3) . '/lib/CactiProcessLock.php';
|
|
|
|
test('task keys are deterministic and preserve field boundaries', function () {
|
|
$key = CactiProcessLock::key('poller', 'child', 7);
|
|
|
|
expect($key)->toBe(CactiProcessLock::key('poller', 'child', 7))
|
|
->and($key)->toStartWith('cacti.process.')
|
|
->and(strlen($key))->toBe(78)
|
|
->and($key)->not->toBe(CactiProcessLock::key('poller:child', '7', 0))
|
|
->and($key)->not->toBe(CactiProcessLock::key('poller', 'child', 8));
|
|
});
|
|
|
|
test('only one owner can hold a task lock at a time', function () {
|
|
$factory = new LockFactory(new InMemoryStore());
|
|
$first = new CactiProcessLock($factory, 'poller', 'master', 0);
|
|
$second = new CactiProcessLock($factory, 'poller', 'master', 0);
|
|
|
|
expect($first->acquire())->toBeTrue()
|
|
->and($second->acquire())->toBeFalse();
|
|
|
|
$first->release();
|
|
|
|
expect($second->acquire())->toBeTrue();
|
|
|
|
$second->release();
|
|
});
|
|
|
|
test('pdo locks use the declared schema and release ownership', function () {
|
|
$connection = new PDO('sqlite::memory:');
|
|
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
|
|
|
|
$first = CactiProcessLock::fromPdo($connection, 'reports', 'master', 0);
|
|
$second = CactiProcessLock::fromPdo($connection, 'reports', 'master', 0);
|
|
|
|
expect($connection->getAttribute(PDO::ATTR_ERRMODE))->toBe(PDO::ERRMODE_SILENT)
|
|
->and($first->acquire())->toBeTrue()
|
|
->and($connection->getAttribute(PDO::ATTR_ERRMODE))->toBe(PDO::ERRMODE_SILENT)
|
|
->and($connection->query("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'process_locks'")->fetchColumn())->toBe(CactiProcessLock::TABLE)
|
|
->and($second->acquire())->toBeFalse();
|
|
|
|
$first->release();
|
|
|
|
expect($connection->getAttribute(PDO::ATTR_ERRMODE))->toBe(PDO::ERRMODE_SILENT)
|
|
->and($second->acquire())->toBeTrue();
|
|
|
|
$second->release();
|
|
|
|
expect($connection->getAttribute(PDO::ATTR_ERRMODE))->toBe(PDO::ERRMODE_SILENT);
|
|
});
|