Skip to content

Instantly share code, notes, and snippets.

@valpackett
Created March 23, 2023 05:28
Show Gist options
  • Save valpackett/d21448b77cc8c0d2d4502505b6114e5a to your computer and use it in GitHub Desktop.
Save valpackett/d21448b77cc8c0d2d4502505b6114e5a to your computer and use it in GitHub Desktop.
FreeBSD reaper API demo
#include <sys/procctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sysexits.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <signal.h>
int main() {
srandomdev();
if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) err(EX_OSERR, NULL);
printf("reaper: %d\n", getpid());
pid_t one, two;
if ((one = fork()) == 0) {
printf(" one: %d\n", getpid());
usleep(1000 * (random() % 1000 + 200));
if ((one = fork()) == 0) {
printf(" one.child: %d\n", getpid());
usleep(1000 * (random() % 1000 + 200));
if ((one = fork()) == 0) {
printf(" one.child.child1: %d\n", getpid());
while (true) {
printf(" one.child.child1 looping\n");
usleep(1000 * 250);
}
}
usleep(1000 * (random() % 1000 + 200));
if ((one = fork()) == 0) {
printf(" one.child.child2: %d\n", getpid());
while (true) {
printf(" one.child.child2 looping\n");
usleep(1000 * 250);
}
}
usleep(1000 * (random() % 1000 + 200));
printf(" one.child: return\n");
return 0;
}
printf(" one: return\n");
return 0;
}
if ((two = fork()) == 0) {
printf(" two: %d\n", getpid());
sleep(1);
if ((two = fork()) == 0) {
printf(" two.child: %d\n", getpid());
while (true) {
printf(" two.child looping\n");
sleep(1);
}
}
printf(" two: return\n");
return 0;
}
int cnt = 0;
while (true) {
usleep(1000 * 500);
int status = -1;
struct rusage usage = {0};
pid_t reaped = -1;
while ((reaped = wait3(&status, WNOHANG, &usage)) != 0 && reaped != -1)
printf("reaper: reaped %d\n", reaped);
struct procctl_reaper_pidinfo infos[10] = {0};
struct procctl_reaper_pids inforeq = { .rp_count = 10, .rp_pids = infos };
if (procctl(P_PID, getpid(), PROC_REAP_GETPIDS, &inforeq) == -1) err(EX_OSERR, NULL);
printf("reaper: children:\n");
for (size_t i = 0; i < inforeq.rp_count; i++)
if (infos[i].pi_pid != 0)
printf("- pid %d of subtree %d\n", infos[i].pi_pid, infos[i].pi_subtree);
struct procctl_reaper_kill killreq = {
.rk_sig = SIGTERM,
.rk_flags = REAPER_KILL_SUBTREE,
.rk_subtree = one,
.rk_killed = -1,
.rk_fpid = -1,
};
cnt++;
if (cnt == 10) {
printf("reaper: killing one's descendants\n");
if (procctl(P_PID, getpid(), PROC_REAP_KILL, &killreq) == -1) err(EX_OSERR, NULL);
printf("reaper: killed %d procs\n", killreq.rk_killed);
}
if (cnt == 15) {
printf("reaper: killing two's descendants\n");
killreq.rk_subtree = two;
if (procctl(P_PID, getpid(), PROC_REAP_KILL, &killreq) == -1) err(EX_OSERR, NULL);
printf("reaper: killed %d procs\n", killreq.rk_killed);
}
if (cnt == 16) {
printf("reaper: done\n");
return 0;
}
}
}
reaper: 30368
one: 30369
two: 30370
one: return
one.child: 30371
reaper: reaped 30369
reaper: children:
- pid 30371 of subtree 30369
- pid 30370 of subtree 30370
one.child.child1: 30372
one.child.child1 looping
two: return
two.child: 30373
two.child looping
reaper: children:
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
- pid 30371 of subtree 30369
- pid 30370 of subtree 30370
one.child.child1 looping
one.child.child1 looping
reaper: reaped 30370
reaper: children:
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
- pid 30371 of subtree 30369
one.child.child2: 30374
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
- pid 30371 of subtree 30369
one.child.child1 looping
two.child looping
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
- pid 30371 of subtree 30369
one.child.child1 looping
one.child.child2 looping
one.child.child1 looping
one.child: return
reaper: reaped 30371
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
two.child looping
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
one.child.child1 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
one.child.child1 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
two.child looping
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
one.child.child1 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
one.child.child2 looping
one.child.child1 looping
one.child.child2 looping
one.child.child1 looping
reaper: children:
- pid 30374 of subtree 30369
- pid 30373 of subtree 30370
- pid 30372 of subtree 30369
reaper: killing one's descendants
reaper: killed 2 procs
two.child looping
reaper: reaped 30372
reaper: reaped 30374
reaper: children:
- pid 30373 of subtree 30370
two.child looping
reaper: children:
- pid 30373 of subtree 30370
reaper: children:
- pid 30373 of subtree 30370
two.child looping
reaper: children:
- pid 30373 of subtree 30370
reaper: children:
- pid 30373 of subtree 30370
reaper: killing two's descendants
reaper: killed 1 procs
reaper: reaped 30373
reaper: children:
reaper: done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment