Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Care about children of supervised processes #33

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions rts.tests/supervise-orphanage.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--- supervise properly runs an orphanage
the first run
test.sv: up (pid x) x seconds, normally down, running
Caught TERM
test.sv: up (pid x) x seconds, normally down, orphanage
the second run
Caught HUP
43 changes: 43 additions & 0 deletions rts.tests/supervise-orphanage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
echo '--- supervise properly runs an orphanage'
catexe test.sv/run <<EOF
#!/bin/sh
nohup ../../sleeper >output &
mv run2 run
echo the first run
exec ../../sleeper
EOF
catexe test.sv/run2 <<EOF
#!/bin/sh
echo the second run
svc -x .
EOF
touch test.sv/orphanage
supervise test.sv &
until svok test.sv || ! jobs %% >/dev/null 2>&1
do
sleep 1
done
if svok test.sv
then
svc -u test.sv
while [ -e test.sv/run2 ]
do
sleep 1
done
svstat test.sv | filter_svstat
svc -t test.sv
until svstat test.sv | grep -q orphanage
do
sleep 1
done
svstat test.sv | filter_svstat
cat test.sv/output
svc -+h test.sv
wait
cat test.sv/output
else
echo "This test fails on older Unix systems"
echo "(everything which is not Linux or FreeBSD)"
echo "as they have no subprocess reapers"
fi
rm test.sv/orphanage
34 changes: 34 additions & 0 deletions subreaper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "strerr.h"

#ifdef __linux__
#include <sys/prctl.h>

#ifdef PR_SET_CHILD_SUBREAPER
#define HAS_SUBREAPER 1

extern int set_subreaper(void)
{
return prctl(PR_SET_CHILD_SUBREAPER,1,0,0,0);
}

#endif
#endif

#ifdef __FreeBSD__
#include <sys/procctl.h>
#ifdef PROC_REAP_ACQUIRE
#define HAS_SUBREAPER 1

extern int set_subreaper(void)
{
return procctl(P_PID,0,PROC_REAP_ACQUIRE,NULL);
}
#endif
#endif

#ifndef HAS_SUBREAPER
extern int set_subreaper(void)
{
return -1;
}
#endif
8 changes: 8 additions & 0 deletions subreaper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* Public domain. */

#ifndef SUBREAPER_H
#define SUBREAPER_H

extern int set_subreaper(void);

#endif
8 changes: 8 additions & 0 deletions supervise.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ The fourth is the exit code or kill signal number, or
.B 0
on start.

If the file
.IB s /orphanage
exists,
.B supervise
will wait until all ancestors of the supervised process have also exited,
before it will consider the process stopped. In the meantime, the process
is considered to be in an "orphanage" state.

.B supervise
maintains status information in a binary format inside the directory
.IR s\fB/supervise ,
Expand Down
20 changes: 18 additions & 2 deletions supervise.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "iopause.h"
#include "taia.h"
#include "deepsleep.h"
#include "subreaper.h"
#include "stralloc.h"
#include "svpath.h"
#include "svstatus.h"
Expand Down Expand Up @@ -44,6 +45,7 @@ int fdok;
int fdstatus;

int flagexit = 0;
int flagorphanage = 0;
int firstrun = 1;
const char *runscript = 0;

Expand Down Expand Up @@ -295,11 +297,18 @@ void doit(void)
for (;;) {
r = wait_nohang(&wstat);
if (!r) break;
if ((r == -1) && (errno != error_intr)) break;
if (r == svcmain.pid)
if (flagorphanage && r == svcmain.pid) {
svcmain.flagstatus = svstatus_orphanage;
announce();
continue;
}
if ((r == svcmain.pid) || ((svcmain.flagstatus == svstatus_orphanage)
&& (r == -1) && (errno == ECHILD)))
svc = &svcmain;
else if (r == svclog.pid)
svc = &svclog;
else if ((r == -1) && (errno != error_intr))
break;
else
continue;
killpid = svc->pid;
Expand Down Expand Up @@ -444,9 +453,16 @@ int main(int argc,char **argv)
if (!svpath_init())
strerr_die3sys(111,FATAL,"unable to setup control path for ",dir);

if (stat_exists("orphanage") != 0) {
flagorphanage = 1;
if (set_subreaper())
strerr_die2sys(111,FATAL,"could not set subreaper attribute");
}
if (stat_isexec("log") > 0) {
if (pipe(logpipe) != 0)
strerr_die3sys(111,FATAL,"unable to create pipe for ",dir);
else if (flagorphanage)
strerr_die2sys(111,FATAL,"orphanage and log are mutually exclusive");
svclog.flagwantup = 1;
}
if (stat("down",&st) != -1) {
Expand Down
1 change: 1 addition & 0 deletions supervise=x
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
deepsleep.o
svpath.o
subreaper.o
time.a
unix.a
byte.a
1 change: 1 addition & 0 deletions svstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ static void showstatus(const char status[19], int r, int normallyup)
case svstatus_running: x = ", running"; break;
case svstatus_stopping: x = ", stopping"; break;
case svstatus_failed: x=", failed"; break;
case svstatus_orphanage: x=", orphanage"; break;
default: x = ", status unknown";
}
if (pid && (want == '\000'))
Expand Down
1 change: 1 addition & 0 deletions svstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum svstatus {
svstatus_running,
svstatus_stopping,
svstatus_failed,
svstatus_orphanage,
};

#endif