mirror of
https://github.com/Cacti/spine.git
synced 2026-10-25 20:47:13 +09:00
## Summary - make subprocess-registry detach atomic so exactly one closer owns each entry - make cancellation cleanup release only the detached node it owns - replace `vfork`/`execve` child setup with `posix_spawn` and explicit file actions - mark every pipe and stdio-collision duplicate close-on-exec - restore the child's default SIGPIPE disposition while preserving the parent's handling - bound TERM/KILL reaping and park unreaped children in a fixed-capacity sweep list - harden PHP script-server slot ownership, startup, restart, signal, descriptor, and cleanup paths - retire and restart failed or oversized reads so stale response tails cannot poison later data sources - revalidate every command retry and cap recovery handshakes at two seconds This folds the child-process lifecycle portion of #597 into the narrower ownership PR. It does not absorb unrelated poll-host, SQL, SNMP, ICMP, or build-infrastructure work. ## Review-driven corrections - close-on-exec is explicitly restored after `dup()` in both read and write stdio-collision branches - the source invariant check now uses portable POSIX character classes - direct tests cover duplicate flags, both collision branches, failure after pipe creation, abandoned-child sweeping, and capacity overflow - collision cleanup preserves current-child redirects even when an older registry entry occupies fd 0 or 1 - script children receive SIGTERM before SIGKILL and unreaped PHP children transfer to the bounded sweep registry - the Docker integration suite now starts a real PHP script server, verifies its startup protocol and database result, and checks that shutdown leaves no zombie PHP process ## Validation - Ubuntu 24.04 container with GCC and GNU ld: `make check`, 6/6 targets passed with no skips, including `test_php_runtime` - real PHP script-server Docker integration: 6/6 checks passed; exact value `42` reached `poller_output` and no zombie remained - macOS Homebrew dependency build passed - macOS `make check`: 5/5 available binaries passed; GNU `--wrap` runtime suite is Linux-only - PHP fixture syntax checked through mise PHP 8.3 - actionlint, shellcheck, and `git diff --check` passed Closes #610. --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> Co-authored-by: TheWitness <thewitness@cacti.net>
33 lines
815 B
C
33 lines
815 B
C
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
|
|
int main(int argc, char **argv) {
|
|
char command[4096];
|
|
const char *mode = argc > 2 ? argv[2] : "";
|
|
if (strstr(mode, "exit-before-start") != NULL) return 0;
|
|
|
|
if (strstr(mode, "silent") == NULL) {
|
|
struct sigaction action;
|
|
int bad_start = strstr(mode, "bad-start") != NULL;
|
|
|
|
if (strstr(mode, "check-sigpipe") != NULL &&
|
|
(sigaction(SIGPIPE, NULL, &action) != 0 || action.sa_handler != SIG_DFL)) {
|
|
bad_start = 1;
|
|
}
|
|
puts(bad_start ? "Not ready" : "Started");
|
|
fflush(stdout);
|
|
}
|
|
|
|
while (fgets(command, sizeof(command), stdin) != NULL) {
|
|
if (strcmp(command, "quit\r\n") == 0 || strcmp(command, "quit\n") == 0) {
|
|
break;
|
|
}
|
|
|
|
puts(strcmp(command, "poll 7\r\n") == 0 ? "42" : "unexpected command");
|
|
fflush(stdout);
|
|
}
|
|
|
|
return 0;
|
|
}
|