Code cleanup, make process termination more robust and add debugging output to tuxreaperd

This commit is contained in:
mrkmntal 2026-08-29 13:08:32 -04:00
commit 2f75d914ab
2 changed files with 35 additions and 19 deletions

View file

@ -196,11 +196,10 @@ static inline long sys_close(int fd) {
static inline long sys_clock_gettime(int clk_id, struct timespec *tp) { static inline long sys_clock_gettime(int clk_id, struct timespec *tp) {
long ret; long ret;
register long r10 __asm__("r10") = 0;
__asm__ volatile ( __asm__ volatile (
"syscall" "syscall"
: "=a"(ret) : "=a"(ret)
: "a"(228), "D"((long)clk_id), "S"(tp), "r"(r10) : "a"(228), "D"((long)clk_id), "S"(tp)
: "rcx", "r11", "memory" : "rcx", "r11", "memory"
); );
return ret; return ret;
@ -592,6 +591,7 @@ static const char * const apache_exes[] = {
#define DESCENDANT_TIMEOUT_SECONDS 60 #define DESCENDANT_TIMEOUT_SECONDS 60
#define BROADCAST_SCAN_DELAY_US 100000 #define BROADCAST_SCAN_DELAY_US 100000
#define DESCENDANT_POLL_INTERVAL_US 50000
#define AT_FDCWD -100 #define AT_FDCWD -100
#define O_RDONLY 0 #define O_RDONLY 0
@ -793,7 +793,7 @@ static volatile int g_pending_signals = 0;
static void proxy_sig_handler(int sig) { static void proxy_sig_handler(int sig) {
if (sig >= 1 && sig <= 31) { if (sig >= 1 && sig <= 31) {
g_pending_signals |= (1 << (sig - 1)); g_pending_signals |= (1U << (sig - 1));
} }
} }
@ -820,7 +820,7 @@ static void handle_pending_signals(void) {
g_pending_signals = 0; g_pending_signals = 0;
for (int sig = 1; sig <= 31; sig++) { for (int sig = 1; sig <= 31; sig++) {
if (!(pending & (1 << (sig - 1)))) continue; if (!(pending & (1U << (sig - 1)))) continue;
#ifdef TUXREAPERD_DEBUG #ifdef TUXREAPERD_DEBUG
debug_write("[tuxreaperd] handling pending signal "); debug_write("[tuxreaperd] handling pending signal ");
debug_write_int(sig); debug_write_int(sig);
@ -909,6 +909,7 @@ int main(int argc, char **argv, char **envp) {
debug_msg("main child exited, waiting up to 60s for descendants"); debug_msg("main child exited, waiting up to 60s for descendants");
} }
drain_zombies();
int descendants = count_descendants(); int descendants = count_descendants();
#ifdef TUXREAPERD_DEBUG #ifdef TUXREAPERD_DEBUG
debug_write("[tuxreaperd] descendants="); debug_write("[tuxreaperd] descendants=");
@ -923,12 +924,19 @@ int main(int argc, char **argv, char **envp) {
debug_msg("descendant timeout reached, exiting"); debug_msg("descendant timeout reached, exiting");
break; break;
} }
/* Poll briefly so the 60-second deadline can tick even if no
SIGCHLD or external signal arrives. handle_pending_signals()
catches any signal that was delivered while we slept. */
sleep_us(DESCENDANT_POLL_INTERVAL_US);
handle_pending_signals();
} else {
/* Workload active: block atomically with zero CPU wakeups until a
signal arrives. */
sys_rt_sigsuspend(&old_mask, sizeof(old_mask));
drain_zombies();
handle_pending_signals();
} }
sys_rt_sigsuspend(&old_mask, sizeof(old_mask));
drain_zombies();
handle_pending_signals();
} }
drain_zombies(); drain_zombies();

View file

@ -46,6 +46,10 @@ static const char * const apache_exes[] = {
processes that spawned just after the first scan. */ processes that spawned just after the first scan. */
#define BROADCAST_SCAN_DELAY_US 100000 #define BROADCAST_SCAN_DELAY_US 100000
/* How often to poll while waiting for descendants after the main child exits.
Short enough to react quickly, long enough to avoid burning CPU. */
#define DESCENDANT_POLL_INTERVAL_US 50000
static volatile pid_t g_main_child = 0; static volatile pid_t g_main_child = 0;
static volatile sig_atomic_t g_child_exited = 0; static volatile sig_atomic_t g_child_exited = 0;
static volatile int g_main_status = 0; static volatile int g_main_status = 0;
@ -231,8 +235,6 @@ int main(int argc, char *argv[]) {
long long child_exit_time_ms = 0; long long child_exit_time_ms = 0;
while (1) { while (1) {
int descendants = 0;
if (g_child_exited) { if (g_child_exited) {
long long now = monotonic_ms(); long long now = monotonic_ms();
if (child_exit_time_ms == 0) { if (child_exit_time_ms == 0) {
@ -241,7 +243,8 @@ int main(int argc, char *argv[]) {
DESCENDANT_TIMEOUT_SECONDS); DESCENDANT_TIMEOUT_SECONDS);
} }
descendants = count_descendants(); drain_zombies();
int descendants = count_descendants();
debug("[tuxreaperd] descendants=%d", descendants); debug("[tuxreaperd] descendants=%d", descendants);
if (descendants == 0) { if (descendants == 0) {
@ -253,14 +256,19 @@ int main(int argc, char *argv[]) {
debug("[tuxreaperd] descendant timeout reached, exiting"); debug("[tuxreaperd] descendant timeout reached, exiting");
break; break;
} }
// Poll briefly so the 60-second deadline can tick even if no
// SIGCHLD or external signal arrives. handle_pending_signals()
// catches any signal that was delivered while we slept.
usleep(DESCENDANT_POLL_INTERVAL_US);
handle_pending_signals();
} else {
// Workload active: block atomically with zero CPU wakeups until a
// signal arrives.
sigsuspend(&old_mask);
drain_zombies();
handle_pending_signals();
} }
// Wait for a signal. When one arrives, reap and handle it, then loop
// back to re-evaluate descendants and timeouts.
sigsuspend(&old_mask);
drain_zombies();
handle_pending_signals();
} }
// Final sweep of any remaining lingering zombies. // Final sweep of any remaining lingering zombies.