Skip to content

Commit

Permalink
svscan: issue SIGKILL after KILLWAIT secs
Browse files Browse the repository at this point in the history
1. systemd.in: replace /etc/init.d/svscan with /usr/bin/qmailctl for ExeStop
2. svscan.c: when running as init issue SIGKILL after KILLWAIT secs
  • Loading branch information
mbhangui committed Feb 26, 2024
1 parent a037f09 commit 8eac7cd
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 46 deletions.
3 changes: 3 additions & 0 deletions daemontools-x/doc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ Release 1.1.3-1.1 Start 27/04/2023 End 01/01/2024
17. multilog.c: use unlinkat() if available instead of unlink
- 18/02/2024
19. multilog.c: BUG: fix wrong argument passed to open_read() in finish()
- 26/02/2024
20. systemd.in: replace /etc/init.d/svscan with /usr/bin/qmailctl for ExeStop
21. svscan.c: when running as init issue SIGKILL after KILLWAIT secs

* Sun Apr 23 2023 17:05:00 +0000 Manvendra Bhangui <daemontools@indimail.org> 1.1.2-1.1%{?dist}
Release 1.1.2-1.1 Start 20/02/2023 End 23/04/2023
Expand Down
26 changes: 15 additions & 11 deletions daemontools-x/svscan.9
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ svscan \- starts and monitors a collection of services

.SH DESCRIPTION
\fBsvscan\fR(8) starts one \fBsupervise\fR(8) process for each subdirectory
of the current directory, up to a limit of 1000 subdirectories.
\fBsvscan\fR(8) skips subdirectory names starting with dots.
\fBsupervise\fR(8) must be in \fBsvscan\fR's path. \fBsvscan\fR(8) calls
\fBsetsid(2)\fR to become a session leader if the environment variable
\fBSETSID\fR is set. When running as a session leader, svscan will
terminate process group if the environment vairable \fBTERMINATE_SESSION\fR
is set. This will terminate all supervise proceses started by \fBsvscan\fR.
The call kill(0, 15) is used to achieve this. If \fBsvscan\fR(8) is given a
command-line argument \fIdirectory\fR, it switches to that directory when
it starts.
of the current directory, up to a limit of 1000 subdirectories. If
\fBsvscan\fR(8) is given a command-line argument \fIdirectory\fR, it
switches to that directory when it starts. \fBsvscan\fR(8) skips
subdirectory names starting with dots. \fBsupervise\fR(8) must be in
\fBsvscan\fR's path. \fBsvscan\fR(8) calls \fBsetsid(2)\fR to become a
session leader if the environment variable \fBSETSID\fR is set. When
running as a session leader, svscan will terminate process group if the
environment vairable \fBTERMINATE_SESSION\fR is set. This will terminate
all supervise proceses started by \fBsvscan\fR. The call kill(0, 15) is
used to achieve this.

\fBsvscan\fR(8) optionally starts a pair of \fRsupervise\fR(8) processes,
one for a subdirectory \fIs\fR, one for \fIs\fR/\fIlog\fR, with a pipe
Expand Down Expand Up @@ -101,7 +101,11 @@ require. If running as PID 1, \fBsvscan\fR will immediately restart a
\fBsupervise\fR process if it dies, rather waiting for 60 (or SCANINTERVAL)
seconds. This behaviour can be enabled as default by setting \fBSCANNOW\fR
environment variable. Setting this variable enables a signal handler for
\fBSIGCHILD\fR.
\fBSIGCHILD\fR. When running as PID 1 and \fBsvscan\fR receives a TERM
signal, it will send TERM signal to the entire process group and wait for
60 seconds before sending KILL signal to the entire process group. The
default of 60 seconds can be changed by setting \fBKILL_WAIT\fR environment
variable.

If \fBINITCMD\fR environment variable is defined and set to an empty string
and if \fI@servicedir@\fR/.\fIsvscan\fR/\fIrun\fR exists and has the
Expand Down
82 changes: 66 additions & 16 deletions daemontools-x/svscan.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/*
* $Id: svscan.c,v 1.33 2023-06-05 19:00:51+05:30 Cprogrammer Exp mbhangui $
* $Id: svscan.c,v 1.34 2024-02-26 16:59:01+05:30 Cprogrammer Exp mbhangui $
*/
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <direntry.h>
Expand Down Expand Up @@ -81,45 +82,93 @@ initialize_run()
#endif

void
init_cmd(char *cmmd, int dowait, int shutdown)
init_cmd(char *cmmd, int shutdown)
{
int child, r, wstat;
int child, r, wstat, did_kill = 0, do_wait;
unsigned int w;
pid_t pid;
char *cpath, *args[4];
char *cpath, *p, *terminate_session, *args[4];
char strnum[FMT_ULONG];
time_t starttime, t;

if (shutdown)
sig_block(sig_child);
cpath = shutdown ? SVSCANINFO"/shutdown" : cmmd && *cmmd ? cmmd : SVSCANINFO"/run";
if (access(cpath, X_OK))
return;
pid = getpid();
strnum[fmt_ulong(strnum, pid)] = 0;
switch (child = fork())
{
case -1:
strerr_die4sys(111, FATAL, "unable to fork for init command ", cpath, ": ");
return;
case 0:
if (shutdown)
sig_block(sig_term);
args[0] = "/bin/sh";
args[1] = "-c";
args[2] = cpath;
args[3] = 0;
strnum[fmt_ulong(strnum, pid)] = 0;
if (!env_put2("PPID", strnum))
strerr_die3x(111, WARN, cpath, "init_cmd: out of memory");
execv(*args, args);
strerr_die4sys(111, WARN, "unable to run", cpath, ": ");
default:
break;
}
do_wait = env_get("WAIT_INITCMD") ? 1 : 0;
terminate_session = shutdown ? env_get("TERMINATE_SESSION") : 0;
if (pid == 1) {
if (!do_wait && !shutdown)
return;
starttime = time((time_t *) NULL);
if ((p = env_get("KILLWAIT")))
scan_uint(p, &w);
else
w = 60;
} else
if (!do_wait) {
if (shutdown && terminate_session)
kill(0, sig_term);
return;
}
/*
* we come here when
* PID is 1 and do_wait is 1 or shutdown is 1
* PID is > 1 and do_wait is 1
*/
for (;;) {
r = dowait ? wait_pid(&wstat, child) : wait_nohang(&wstat);
if (!r || (dowait && r == child))
break;
r = (pid == 1 && shutdown) ? wait_nohang(&wstat) : wait_pid(&wstat, child);
if (r == -1) {
if (errno == error_intr)
continue; /*- impossible */
continue; /*- impossible for wait_nohang */
break;
}
}
if (!r)
break;
if (pid == 1 && shutdown) { /* wait_nohang was called */
if (!did_kill) {
did_kill = 1;
strerr_warn4(INFO, "pid: ", strnum, ": terminating session with TERM...", 0);
kill(0, sig_term);
}
if (did_kill == 1) {
t = time((time_t *) NULL) - starttime;
if (t > w) {
did_kill = 2;
strerr_warn4(INFO, "pid: ", strnum, ": terminating session with KILL...", 0);
kill(0, SIGKILL);
if (!kill(child, 0))
kill(child, SIGKILL);
}
}
strerr_warn4(INFO, "pid: ", strnum, ": waiting for processes to shutdown...", 0);
sleep(did_kill == 1 ? w : 5);
continue;
} else /*- wait_pid on child was called */
break;
} /*- for (;;) */
return;
}

Expand Down Expand Up @@ -476,7 +525,7 @@ doit(char *sdir, pid_t mypid)
*/
strnum1[fmt_ulong(strnum1, r)] = 0;
if (wait_stopped(wstat) || wait_continued(wstat)) {
t = wait_stopped(wstat) ? wait_stopsig(wstat) : SIGCONT;
t = wait_stopped(wstat) ? wait_stopsig(wstat) : sig_cont;
strnum2[fmt_ulong(strnum2, t)] = 0;
if (p_exe_name)
strerr_warn7(INFO, "pid: ", strnum1, " exe ", p_exe_name,
Expand Down Expand Up @@ -568,9 +617,7 @@ sigterm(int i)
signal(SIGTERM, SIG_IGN);
strnum[fmt_ulong(strnum, getpid())] = 0;
strerr_warn4(INFO, "pid: ", strnum, ": shutdown...", 0);
init_cmd(0, 1, 1); /*- run .svscan/shutdown */
if (sess_leader && env_get("TERMINATE_SESSION"))
kill(0, 15);
init_cmd(0, 1); /*- run .svscan/shutdown */
_exit(0);
}

Expand Down Expand Up @@ -816,7 +863,7 @@ main(int argc, char **argv)
if (env_get("SCANLOG"))
open_svscan_log(sdir);
if ((s = env_get("INITCMD")))
init_cmd(s, env_get("WAIT_INITCMD") ? 1 : 0, 0);
init_cmd(s, 0);
auto_scan = env_get("AUTOSCAN") ? 1 : 0;
for (i = 0; i < numx; ++i)
x[i].flagwantup = -1;
Expand Down Expand Up @@ -859,13 +906,16 @@ main(int argc, char **argv)
void
getversion_svscan_c()
{
static char *y = "$Id: svscan.c,v 1.33 2023-06-05 19:00:51+05:30 Cprogrammer Exp mbhangui $";
static char *y = "$Id: svscan.c,v 1.34 2024-02-26 16:59:01+05:30 Cprogrammer Exp mbhangui $";

y++;
}

/*
* $Log: svscan.c,v $
* Revision 1.34 2024-02-26 16:59:01+05:30 Cprogrammer
* when running as init issue SIGKILL after KILLWAIT secs
*
* Revision 1.33 2023-06-05 19:00:51+05:30 Cprogrammer
* turn on verbose, silent using env variables VERBOSE, SILENT
*
Expand Down
41 changes: 22 additions & 19 deletions daemontools-x/systemd.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
#
# $Id: systemd.in,v 1.10 2024-02-26 02:08:36+05:30 Cprogrammer Exp mbhangui $
#
[Unit]
Description=SVscan Service
After=local-fs.target network.target

[Service]
ExecStart=@libexecdir@/svscanboot @servicedir@
ExecStop=/usr/bin/qmailctl stop
Restart=on-failure
RestartSec=10
Type=simple
PrivateTmp=no

[Install]
Alias=indimail.service
Alias=indimail-mta.service
WantedBy=multi-user.target
#
# $Log: systemd.in,v $
# Revision 1.10 2024-02-26 02:08:36+05:30 Cprogrammer
# replace /etc/init.d/svscan with /usr/bin/qmailctl for ExeStop
#
# Revision 1.9 2021-06-22 10:45:21+05:30 Cprogrammer
# added RestartSec parameter and moved PrivateTmp to override.conf
#
Expand Down Expand Up @@ -31,22 +53,3 @@
# Start daemontools
# to start - systemctl start svscan|indimail|indimail-mta
# to stop - systemctl stop svscan|indimail|indimail-mta
#
# $Id: systemd.in,v 1.9 2021-06-22 10:45:21+05:30 Cprogrammer Exp mbhangui $
#
[Unit]
Description=SVscan Service
After=local-fs.target network.target

[Service]
ExecStart=@libexecdir@/svscanboot @servicedir@
ExecStop=/etc/init.d/svscan stop
Restart=on-failure
RestartSec=10
Type=simple
PrivateTmp=no

[Install]
Alias=indimail.service
Alias=indimail-mta.service
WantedBy=multi-user.target

0 comments on commit 8eac7cd

Please sign in to comment.