Commit Graph
2 Commits
Author SHA1 Message Date
Thomas Vincent a155419ff3 Serialize process registry admission with portable locks (#7771)
* 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>
2026-09-04 19:36:42 -07:00
Thomas VincentandTheWitness f2898730e1 fix: guard process registration and cleanup against PID reuse (#7425) (#7574)
* fix: guard process registration and cleanup against PID reuse

A bare posix_kill($pid, 0) only proves some process owns the pid, so a
recycled one blocked new tasks or drew a SIGTERM meant for something else.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: spawn probe children without a wrapping shell

proc_open with a string command runs it via sh, so the child's /proc comm was
sh and the identity check correctly refused to signal it on Linux.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* docs: append the changelog entry at the end of the issue block

Matches .github/copilot-instructions.md, which appends rather than inserting
in numeric order.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix: limit the process identity check to CLI callers

The registry holds CLI tasks, so a web request comparing command names would
never match and would report a running task dead.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: use the full licence header on the new test files

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test: treat CACTI_PATH_LOG as a directory and pass ctor args to the statement class

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix: make process identity checks self-contained

* fix(batchgapfix): guard forced process termination

* fix(processes): preserve live pids on permission errors

* Refresh security baselines after develop rebase

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* Wait for the spawned child to exec before the identity check

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* Serve fetch() from the buffered rows in the process registry fake

db_table_exists() probes with SHOW TABLES, and db_fetch_row_prepared()
reads a single row with fetch(); the fake drained the cursor on execute()
and answered neither, so every registry query came back empty and the
tests exercised the no-processes-table path instead of the guard.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(changelog): drop entries duplicated by an earlier rebase

Only the issue#7425 line belongs to this branch.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* fix(poller): identify a registered process by its executable, not its name

Children are spawned from path_php_binary, so a versioned child and a parent
started as plain php reported different command names for one interpreter.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

* test(poller): skip the alias check where both paths share a command name

Whether a second path to the interpreter yields a second name is the runner's
business; asserting it failed where php is already the plain name.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>

---------

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
2026-08-16 20:12:10 -04:00