aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-05-24 12:45:25 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-05-24 13:50:39 +0300
commit6dd0ec08db301984b8f8f9082f28006d5915c183 (patch)
treee916ad37fbd3cbcaf85103667f28e0d47f3c2e45 /src/progman.c
parent2a646ee7cbbcb6f4bbd8f38bb3c1e1418550f3fc (diff)
downloadpies-6dd0ec08db301984b8f8f9082f28006d5915c183.tar.gz
pies-6dd0ec08db301984b8f8f9082f28006d5915c183.tar.bz2
Initial implementation of "startup" components.
These are components that are run at program startup. Starting other components is delayed until all startup components terminate. This is similar to SysV "bootwait" components. Upon termination, startup components are removed from the configuration. They are not renewed upon configuratuion reload. * src/comp.c (comp_array_remove): Remove from the depmap as well. (component_ref_decr): Use comp_array_remove for active components and plain component_free for inactive ones. (component_build_depmap): Use comp_array_remove. (component_config_commit): Special handling for pies_comp_startup components. * src/pies.c (modetab): New component modes: "startup" and "shutdown". (main): Run program_init_startup. * src/pies.h (pies_comp_mode): New modes: pies_comp_startup and pies_comp_shutdown. (program_init_startup): New proto. * src/progman.c (progman_waiting_p): Return 1 if a startup component is still running. (program_init_startup): New function. (progman_cleanup): Handle pies_comp_startup termination. * src/socket.c (switch_eids): Avoid unnecessary calls to setegid and seteuid. * tests/atlocal.in (auxdir): New variable. * tests/mailer: Move to tests/aux/ * tests/respawn: Move to tests/aux/ * tests/retcode: Move to tests/aux/ * tests/aux/startup: New auxiliary program. * tests/redirect.at: Start components from $auxdir. * tests/respawn.at: Likewise. * tests/ret-exec.at: Likewise. * tests/ret-notify.at: Likewise. * tests/startup.at: New file. * tests/testsuite.at: Include startup.at * tests/Makefile.am: Add new tests.
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c291
1 files changed, 167 insertions, 124 deletions
diff --git a/src/progman.c b/src/progman.c
index 1b09cd5..5bc4eb3 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -67,3 +67,3 @@ progman_lookup_component (const char *tag)
return NULL;
-}
+}
@@ -124,3 +124,3 @@ link_prog (struct prog *prog, struct prog *ref)
prog->next = ref->next;
-
+
if ((x = ref->next))
@@ -153,3 +153,3 @@ destroy_prog (struct prog **pp)
struct prog *p = *pp;
-
+
unlink_prog (p);
@@ -160,4 +160,4 @@ destroy_prog (struct prog **pp)
if (p->v.p.status == status_listener && p->v.p.socket != -1)
- deregister_socket (p->v.p.socket);
- /* FIXME: Remove also all dependent progs (esp. tcpmux) */
+ deregister_socket (p->v.p.socket);
+ /* FIXME: Remove also all dependent progs (esp. tcpmux) */
if (p->v.p.redir[RETR_OUT])
@@ -167,3 +167,3 @@ destroy_prog (struct prog **pp)
break;
-
+
case TYPE_REDIRECTOR:
@@ -184,3 +184,3 @@ destroy_prog (struct prog **pp)
break;
-
+
case TYPE_COMMAND:
@@ -258,3 +258,3 @@ find_prog_ref (struct component *comp)
}
-
+
if (comp->prog)
@@ -272,3 +272,3 @@ find_prog_ref (struct component *comp)
}
-
+
static struct prog *
@@ -277,3 +277,3 @@ register_prog0 (struct component *comp)
struct prog *newp;
-
+
newp = grecs_zalloc (sizeof (*newp));
@@ -293,3 +293,3 @@ register_prog0 (struct component *comp)
newp->active = 1;
-
+
if (comp->mode != pies_comp_exec)
@@ -319,2 +319,15 @@ register_command (char *tag, char *command, pid_t pid)
+static inline int
+progman_startup_phase (void)
+{
+ struct prog *prog;
+
+ for (prog = proghead; prog; prog = prog->next)
+ {
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ return 1;
+ }
+ return 0;
+}
+
int
@@ -323,6 +336,8 @@ progman_waiting_p (void)
struct prog *prog;
-
+
for (prog = proghead; prog; prog = prog->next)
{
- if (IS_COMPONENT (prog) && prog->wait && prog->pid > 0)
+ if (IS_COMPONENT (prog)
+ && prog->pid > 0
+ && (prog->wait || prog->v.p.comp->mode == pies_comp_startup))
{
@@ -408,3 +423,3 @@ open_redirector (struct prog *master, int stream)
return redirect_to_file (master, stream);
-
+
case redir_syslog:
@@ -412,3 +427,3 @@ open_redirector (struct prog *master, int stream)
}
-
+
if (pipe (p))
@@ -418,3 +433,3 @@ open_redirector (struct prog *master, int stream)
}
-
+
switch (pid = fork ())
@@ -430,6 +445,6 @@ open_redirector (struct prog *master, int stream)
close_fds (&fdset);
-
+
diag_setup (0);
signal_setup (redir_exit);
-
+
close (p[1]);
@@ -443,3 +458,3 @@ open_redirector (struct prog *master, int stream)
_exit (0);
-
+
case -1:
@@ -468,3 +483,3 @@ conn_class_hasher (void *data, unsigned long n_buckets)
size_t len;
-
+
while ((ch = *tag++))
@@ -532,3 +547,3 @@ conn_class_lookup (const char *tag,
}
-
+
probe->count = 0;
@@ -727,3 +742,3 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
size_t len;
-
+
if (a && b)
@@ -755,3 +770,3 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
}
-
+
static void
@@ -762,3 +777,3 @@ environ_setup (char **hint)
size_t count, i, j, n;
-
+
if (!hint)
@@ -771,3 +786,3 @@ environ_setup (char **hint)
}
-
+
/* Count new environment size */
@@ -777,3 +792,3 @@ environ_setup (char **hint)
count++;
-
+
for (i = 0; hint[i]; i++)
@@ -783,6 +798,6 @@ environ_setup (char **hint)
new_env = grecs_calloc (count + 1, sizeof new_env[0]);
-
+
/* Populate the environment. */
n = 0;
-
+
if (old_env)
@@ -797,3 +812,3 @@ environ_setup (char **hint)
char *p;
-
+
if (hint[i][0] == '-')
@@ -808,3 +823,3 @@ environ_setup (char **hint)
j = n;
-
+
if ((p = strchr (hint[i], '=')))
@@ -813,3 +828,3 @@ environ_setup (char **hint)
continue; /* Ignore erroneous entry */
- if (p[-1] == '+')
+ if (p[-1] == '+')
new_env[j] = env_concat (hint[i], p - hint[i] - 1,
@@ -837,3 +852,3 @@ environ_setup (char **hint)
free (environ);
-
+
environ = new_env;
@@ -854,3 +869,3 @@ prog_sockenv (struct prog *prog)
const char *proto = NULL;
-
+
if (!(prog->v.p.comp->flags & CF_SOCKENV))
@@ -861,3 +876,3 @@ prog_sockenv (struct prog *prog)
add_env (ENV_SOCKTYPE, proto);
-
+
if (prog->v.p.comp->socket_url)
@@ -870,3 +885,3 @@ prog_sockenv (struct prog *prog)
add_env (ENV_PROTO, proto);
-
+
if (getsockname (prog->v.p.socket,
@@ -922,3 +937,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
time_t now;
-
+
time (&now);
@@ -932,3 +947,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
}
-
+
if (prog->v.p.failcount > max_count)
@@ -940,3 +955,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
}
-
+
return 0;
@@ -963,3 +978,3 @@ check_connection_rate (struct prog *prog)
size_t max_rate = prog->v.p.comp->max_rate
- ? prog->v.p.comp->max_rate : default_max_rate;
+ ? prog->v.p.comp->max_rate : default_max_rate;
if (max_rate && check_rate (prog, 60, max_rate))
@@ -1011,3 +1026,3 @@ prog_start_prologue (struct prog *prog)
}
-
+
environ_setup (prog->v.p.comp->env ?
@@ -1022,3 +1037,3 @@ prog_start_prologue (struct prog *prog)
umask (prog->v.p.comp->umask);
-
+
set_limits (prog_tag (prog),
@@ -1026,3 +1041,3 @@ prog_start_prologue (struct prog *prog)
prog->v.p.comp->limits : pies_limits);
-
+
if (debug_level >= 1)
@@ -1031,3 +1046,3 @@ prog_start_prologue (struct prog *prog)
struct component *comp = prog->v.p.comp;
-
+
logmsg_printf (LOG_DEBUG, "executing");
@@ -1049,3 +1064,3 @@ prog_execute (struct prog *prog)
}
-
+
execvp (prog->v.p.comp->program ?
@@ -1079,3 +1094,3 @@ prog_start (struct prog *prog)
fd_set fdset;
-
+
if (prog->pid > 0 || !IS_COMPONENT (prog))
@@ -1125,3 +1140,3 @@ prog_start (struct prog *prog)
break;
-
+
case pies_comp_accept:
@@ -1141,5 +1156,5 @@ prog_start (struct prog *prog)
}
-
+
debug (1, (_("starting %s"), prog_tag (prog)));
-
+
if (prog->v.p.comp->rmfile)
@@ -1160,3 +1175,3 @@ prog_start (struct prog *prog)
redir[RETR_ERR] = open_redirector (prog, RETR_ERR);
-
+
switch (pid = fork ())
@@ -1169,12 +1184,12 @@ prog_start (struct prog *prog)
switch (prog->v.p.comp->mode)
- {
- case pies_comp_accept:
- case pies_comp_inetd:
+ {
+ case pies_comp_accept:
+ case pies_comp_inetd:
prog_sockenv (prog);
- dup2 (prog->v.p.socket, 0);
- dup2 (prog->v.p.socket, 1);
- close (prog->v.p.socket);
+ dup2 (prog->v.p.socket, 0);
+ dup2 (prog->v.p.socket, 1);
+ close (prog->v.p.socket);
prog->v.p.socket = -1;
- break;
+ break;
@@ -1184,3 +1199,3 @@ prog_start (struct prog *prog)
int fd = console_open (O_RDWR|O_NOCTTY);
- if (fd < 0)
+ if (fd < 0)
{
@@ -1220,4 +1235,4 @@ prog_start (struct prog *prog)
}
- break;
- }
+ break;
+ }
@@ -1238,3 +1253,3 @@ prog_start (struct prog *prog)
}
-
+
/* Close unneeded descripitors */
@@ -1249,4 +1264,4 @@ prog_start (struct prog *prog)
prog_execute (prog);
-
-
+
+
case -1:
@@ -1293,3 +1308,3 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
int rc;
-
+
if (!acl)
@@ -1300,3 +1315,3 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
input.identity = identity;
-
+
rc = pies_acl_check (acl, &input, 1);
@@ -1317,3 +1332,3 @@ fd_report (int fd, const char *msg)
size_t len;
-
+
if (!msg)
@@ -1336,3 +1351,3 @@ fd_report (int fd, const char *msg)
}
-}
+}
@@ -1346,3 +1361,3 @@ _prog_accept (struct prog *p)
struct conn_class *pcclass;
-
+
fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen);
@@ -1353,3 +1368,3 @@ _prog_accept (struct prog *p)
}
-
+
if (debug_level >= 1)
@@ -1396,3 +1411,3 @@ _prog_accept (struct prog *p)
}
-
+
if (check_connection_rate (p))
@@ -1449,3 +1464,3 @@ _prog_wait (struct prog *p)
}
-
+
int
@@ -1458,3 +1473,3 @@ progman_accept (int socket, void *data)
return _prog_accept (p);
-
+
return _prog_wait (p);
@@ -1528,2 +1543,21 @@ progman_recompute_alarm (void)
void
+program_init_startup (void)
+{
+ struct prog *prog;
+
+ for (prog = proghead; prog; prog = prog->next)
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ {
+ debug (1, ("running startup components"));
+ break;
+ }
+
+ for (; prog; prog = prog->next)
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ {
+ prog_start (prog);
+ }
+}
+
+void
progman_start (void)
@@ -1533,5 +1567,6 @@ progman_start (void)
if (progman_waiting_p ())
- /* Noting to do if there are processes left in the previous runlevel */
+ /* Noting to do if there are processes left in the previous runlevel
+ (in sysv-init mode) or startup components running. */
return;
-
+
debug (1, ("starting components"));
@@ -1567,4 +1602,4 @@ check_stopping (struct prog *prog, time_t now)
if (prog->pid == 0)
- logmsg (LOG_EMERG,
- _("INTERNAL ERROR: attempting to kill unexisting process %s"),
+ logmsg (LOG_EMERG,
+ _("INTERNAL ERROR: attempting to kill unexisting process %s"),
prog_tag (prog));
@@ -1627,3 +1662,3 @@ progman_wake_sleeping (int onalrm)
break;
-
+
case status_stopping:
@@ -1636,3 +1671,3 @@ progman_wake_sleeping (int onalrm)
break;
-
+
default:
@@ -1649,3 +1684,3 @@ prog_start_prerequisites (struct prog *prog)
int warned = 0;
-
+
if (!prog->active)
@@ -1657,3 +1692,3 @@ prog_start_prerequisites (struct prog *prog)
struct prog *p;
-
+
if (!comp->prog || comp->flags & CF_PRECIOUS)
@@ -1671,3 +1706,3 @@ prog_start_prerequisites (struct prog *prog)
}
-
+
p = comp->prog;
@@ -1677,6 +1712,6 @@ prog_start_prerequisites (struct prog *prog)
continue;
-
+
case status_stopped:
break;
-
+
case status_listener:
@@ -1702,3 +1737,3 @@ prog_start_prerequisites (struct prog *prog)
depmap_end (pos);
-
+
return ret;
@@ -1759,3 +1794,3 @@ prog_stop (struct prog *prog, int sig)
kill (prog->pid, sig);
-}
+}
@@ -1789,3 +1824,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
prio = LOG_ERR;
-
+
if (WIFEXITED (status))
@@ -1803,3 +1838,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
char const *coremsg = "";
-
+
if (expect_term && WTERMSIG (status) == SIGTERM)
@@ -1825,3 +1860,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
static void propagate_child_exit (pid_t) ATTRIBUTE_NORETURN;
-
+
static void
@@ -1857,3 +1892,3 @@ wordsplit_string (struct wordsplit const *ws)
size_t len = 0;
-
+
for (i = 0; i < count; i++)
@@ -1885,3 +1920,3 @@ send_msg (char *rcpts, const char *msg_text)
size_t size;
-
+
ws.ws_offs = mailer_argc;
@@ -1898,3 +1933,3 @@ send_msg (char *rcpts, const char *msg_text)
debug (1, (_("sending notification to %s"), rcpts));
-
+
/* Copy mailer arguments */
@@ -1913,3 +1948,3 @@ send_msg (char *rcpts, const char *msg_text)
size_t len;
-
+
while (*arg && c_isblank (*arg))
@@ -1936,6 +1971,6 @@ send_msg (char *rcpts, const char *msg_text)
ws.ws_wordv[k] = NULL;
-
+
/* Fork a child: */
child_pid = fork ();
-
+
if (child_pid < 0)
@@ -1957,3 +1992,3 @@ send_msg (char *rcpts, const char *msg_text)
}
-
+
/* Child process */
@@ -1969,3 +2004,3 @@ send_msg (char *rcpts, const char *msg_text)
}
-
+
grand_child_pid = fork ();
@@ -2032,3 +2067,3 @@ notify_get_tag (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
+ return WRDSE_OK;
}
@@ -2041,3 +2076,3 @@ notify_get_termination (char **ret, void *data)
char *s;
-
+
if (WIFEXITED (clos->status))
@@ -2055,5 +2090,5 @@ notify_get_termination (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
+ return WRDSE_OK;
}
-
+
static int
@@ -2064,3 +2099,3 @@ notify_get_retcode (char **ret, void *data)
size_t l = 0;
-
+
if (WIFEXITED (clos->status))
@@ -2074,5 +2109,5 @@ notify_get_retcode (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
-}
-
+ return WRDSE_OK;
+}
+
struct notify_variable
@@ -2092,3 +2127,3 @@ static struct notify_variable notify_vartab[] = {
};
-
+
static int
@@ -2102,3 +2137,3 @@ notify_getvar (char **ret, const char *vptr, size_t vlen, void *data)
}
-
+
static void
@@ -2122,3 +2157,3 @@ notify (const char *tag, int status, struct action *act)
closure.act = act;
-
+
env[PROGRAM_NAME_IDX] = program_name;
@@ -2146,3 +2181,3 @@ status_matches_p (struct action *act, unsigned status)
int i;
-
+
if (act->nstat == 0)
@@ -2186,3 +2221,3 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
close_fds (NULL);
-
+
argv[0] = "/bin/sh";
@@ -2210,3 +2245,3 @@ react (struct prog *prog, int status, pid_t pid)
list = default_component.act_list;
-
+
if (WIFEXITED (status))
@@ -2235,3 +2270,3 @@ react (struct prog *prog, int status, pid_t pid)
struct action *act = ep->data;
-
+
if (status_matches_p (act, retcode))
@@ -2242,3 +2277,3 @@ react (struct prog *prog, int status, pid_t pid)
}
-
+
switch (act->act)
@@ -2249,3 +2284,3 @@ react (struct prog *prog, int status, pid_t pid)
break;
-
+
case action_disable:
@@ -2265,3 +2300,3 @@ react (struct prog *prog, int status, pid_t pid)
}
-
+
if (!list && prog->v.p.comp->mode != pies_comp_inetd)
@@ -2296,3 +2331,3 @@ progman_cleanup (int expect_term)
struct prog *listener = prog->v.p.listener;
-
+
listener->v.p.num_instances--;
@@ -2309,3 +2344,3 @@ progman_cleanup (int expect_term)
}
-
+
prog_stop_redirectors (prog);
@@ -2323,2 +2358,10 @@ progman_cleanup (int expect_term)
}
+ else if (prog->v.p.comp->mode == pies_comp_startup)
+ {
+ debug (1, (_("removing startup component %s, pid=%lu"),
+ prog_tag (prog), (unsigned long)pid));
+ destroy_prog (&prog);
+ if (!progman_startup_phase ())
+ pies_schedule_children (PIES_CHLD_WAKEUP);
+ }
else
@@ -2331,3 +2374,3 @@ progman_cleanup (int expect_term)
prog->v.p.status = status_finished;
-
+
if (prog->wait)
@@ -2353,3 +2396,3 @@ progman_cleanup (int expect_term)
}
-
+
break;
@@ -2373,3 +2416,3 @@ progman_cleanup (int expect_term)
}
-
+
if (!expect_term)
@@ -2391,3 +2434,3 @@ progman_stop_component (struct prog **progptr)
break;
-
+
case status_listener:
@@ -2415,3 +2458,3 @@ progman_stop_component (struct prog **progptr)
break;
-
+
case status_finished:
@@ -2443,3 +2486,3 @@ prog_activate_listener (struct prog *prog)
struct component *comp = prog->v.p.comp;
-
+
logmsg (LOG_INFO, _("activating listener %s"), prog_tag (prog));
@@ -2537,7 +2580,7 @@ progman_gc (void)
}
-
+
/* FIXME: Report remaining programs */
-
+
}
-
+
/* EOF */

Return to:

Send suggestions and report system problems to the System administrator.