aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/comp.c87
-rw-r--r--src/pies.c115
-rw-r--r--src/pies.h38
-rw-r--r--src/progman.c291
-rw-r--r--src/socket.c54
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/atlocal.in2
-rwxr-xr-xtests/aux/mailer (renamed from tests/mailer)0
-rwxr-xr-xtests/aux/respawn (renamed from tests/respawn)0
-rwxr-xr-xtests/aux/retcode (renamed from tests/retcode)0
-rwxr-xr-xtests/aux/startup7
-rw-r--r--tests/redirect.at2
-rw-r--r--tests/respawn.at2
-rw-r--r--tests/ret-exec.at4
-rw-r--r--tests/ret-notify.at6
-rw-r--r--tests/startup.at84
-rw-r--r--tests/testsuite.at1
17 files changed, 442 insertions, 260 deletions
diff --git a/src/comp.c b/src/comp.c
index c3e998a..2346306 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -24,6 +24,11 @@ struct complist
struct component *tail;
};
+/* 0 on the first load, and 1 on all subsequent reloads. Tells the
+ component_config_commit whether we're starting from scratch or just
+ updating an already loaded configuration */
+static int loaded;
+
static struct complist comp_list[2];
static int cur;
@@ -32,13 +37,13 @@ static size_t comp_count;
static pies_depmap_t depmap;
-static int
+static inline int
next_index (void)
{
return (cur + 1) % ARRAY_SIZE (comp_list);
}
-static int
+static inline int
prev_index (void)
{
return (cur + ARRAY_SIZE (comp_list) - 1) % ARRAY_SIZE (comp_list);
@@ -85,6 +90,22 @@ component_append (struct component *comp)
}
void
+comp_array_remove (size_t i)
+{
+ struct component *comp = comp_array[i];
+
+ depmap_remove (depmap, i);
+ while (i < comp_count -1)
+ {
+ comp_array[i] = comp_array[i+1];
+ comp_array[i]->arridx = i;
+ i++;
+ }
+ component_free (comp);
+ comp_count--;
+}
+
+void
component_unlink (struct component *comp)
{
struct complist *list = &comp_list[comp->listidx];
@@ -201,7 +222,12 @@ component_ref_decr (struct component *comp)
{
assert (comp->ref_count > 0);
if (--comp->ref_count == 0)
- component_free (comp);
+ {
+ if (component_is_active (comp))
+ comp_array_remove (comp->arridx);
+ else
+ component_free (comp);
+ }
}
static int
@@ -425,17 +451,6 @@ report_cyclic_dependency (pies_depmap_t dp, size_t idx)
}
void
-comp_array_remove (size_t i)
-{
- struct component *comp = comp_array[i];
- if (i < comp_count - 1)
- memmove (&comp_array[i], &comp_array[i+1],
- (comp_count - i - 1) * sizeof comp_array[0]);
- component_free (comp);
- comp_count--;
-}
-
-void
component_build_depmap (void)
{
size_t i;
@@ -460,7 +475,6 @@ component_build_depmap (void)
"which is not declared"),
comp->tag, tag);
comp_array_remove (i);
- depmap_remove (depmap, i);
continue;
}
depmap_set (depmap, i, tgt);
@@ -497,10 +511,7 @@ component_build_depmap (void)
for (i = 0; i < comp_count;)
if (comp_array[i]->flags & CF_REMOVE)
- {
- comp_array_remove (i);
- depmap_remove (depmap, i);
- }
+ comp_array_remove (i);
else
i++;
@@ -528,22 +539,36 @@ component_config_commit (void)
comp_array = grecs_realloc (comp_array, i * sizeof (comp_array[0]));
comp_count = i;
- /* Rearrange components, registering prog entries for the new ones */
- for (comp = list->head, i = 0; comp; comp = comp->next, i++)
+ /* Rearrange components, registering entries for the new ones */
+ for (comp = list->head, i = 0; comp; )
{
- match = complist_find_match (prev, comp);
- if (match)
+ struct component *next = comp->next;
+ if (loaded && comp->mode == pies_comp_startup)
{
- component_merge (match, comp);
- component_unlink (match);
- match->listidx = cur;
- component_link (match, comp->prev);
+ /* Ignore startup components */
+ component_unlink (comp);
component_free (comp);
- comp = match;
}
- comp_array[i] = comp;
- comp->arridx = i;
+ else
+ {
+ match = complist_find_match (prev, comp);
+ if (match)
+ {
+ component_merge (match, comp);
+ component_unlink (match);
+ match->listidx = cur;
+ component_link (match, comp->prev);
+ component_free (comp);
+ comp = match;
+ }
+ comp_array[i] = comp;
+ comp->arridx = i;
+ i++;
+ }
+ comp = next;
}
+ /* Adjust comp_count */
+ comp_count = i;
/* Mark orphaned progs for termination */
list = &comp_list[prev];
@@ -560,6 +585,8 @@ component_config_commit (void)
for (comp = comp_list[cur].head; comp; comp = comp->next)
if (!comp->prog)
register_prog (comp);
+
+ loaded = 1;
}
static int
diff --git a/src/pies.c b/src/pies.c
index 89c0b7e..98488a6 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -132,7 +132,7 @@ int
config_file_remove (const char *name)
{
struct grecs_list_entry *ep;
-
+
for (ep = config_list->head; ep; ep = ep->next)
{
struct config_file *file = ep->data;
@@ -156,7 +156,7 @@ void
config_file_list_serialize (struct json_value *ar)
{
struct grecs_list_entry *ep;
-
+
for (ep = config_list->head; ep; ep = ep->next)
{
struct config_file *file = ep->data;
@@ -327,7 +327,7 @@ action_free (struct action *act)
free (act->addr);
free (act->message);
free (act->command);
-
+
free (act);
}
@@ -359,7 +359,7 @@ create_action (struct component *comp,
unsigned n;
const char *arg = getarg (val, i, locus);
size_t len = strlen (arg);
-
+
if (isdigit (arg[0]))
{
char *p;
@@ -394,12 +394,12 @@ create_action (struct component *comp,
grecs_error (locus, 0, _("%s: not a return code"), arg);
continue;
}
-
+
/* Alles in ordnung */
retv[retc++] = n;
}
}
-
+
if (retc == 0 && !allflag)
{
free (retv);
@@ -472,18 +472,18 @@ return_code_section_parser (enum grecs_callback_command cmd,
grecs_error (locus, 0, _("missing tag"));
return 1;
}
-
+
switch (value->type)
{
case GRECS_TYPE_STRING:
act = create_action (comp, locus, value, 1, _get_string_arg);
break;
-
+
case GRECS_TYPE_ARRAY:
act = create_action (comp, locus, value,
value->v.arg.c, _get_array_arg);
break;
-
+
case GRECS_TYPE_LIST:
count = grecs_list_size (value->v.list);
act = create_action (comp, locus, value, count, _get_list_arg);
@@ -492,7 +492,7 @@ return_code_section_parser (enum grecs_callback_command cmd,
return 1;
*(struct action **) cb_data = act;
break;
-
+
case grecs_callback_section_end:
break;
@@ -542,7 +542,7 @@ _cb_command (enum grecs_callback_command cmd,
wordsplit_get_words (&ws, &comp->argc, &comp->argv);
wordsplit_free (&ws);
break;
-
+
case GRECS_TYPE_ARRAY:
comp->argv = config_array_to_argv (value, locus, &comp->argc);
break;
@@ -702,7 +702,7 @@ _cb_redir (enum grecs_callback_command cmd,
{NULL}
};
int res;
-
+
switch (value->type)
{
case GRECS_TYPE_STRING:
@@ -719,7 +719,7 @@ _cb_redir (enum grecs_callback_command cmd,
return 0;
}
break;
-
+
case GRECS_TYPE_ARRAY:
if (assert_grecs_value_type (locus, value->v.arg.v[0],
GRECS_TYPE_STRING))
@@ -739,12 +739,12 @@ _cb_redir (enum grecs_callback_command cmd,
if (assert_grecs_value_type (locus, value->v.arg.v[1],
GRECS_TYPE_STRING))
return 0;
-
+
switch (res)
{
case redir_null:
break;
-
+
case redir_syslog:
if (string_to_syslog_priority (value->v.arg.v[1]->v.string,
&rp->v.prio))
@@ -755,7 +755,7 @@ _cb_redir (enum grecs_callback_command cmd,
return 0;
}
break;
-
+
case redir_file:
rp->v.file = grecs_strdup (value->v.arg.v[1]->v.string);
break;
@@ -764,17 +764,17 @@ _cb_redir (enum grecs_callback_command cmd,
rp->type = res;
}
break;
-
+
default:
grecs_error (locus, 0, _("unexpected list"));
}
-
+
return 0;
}
static struct tokendef socktype_xtab[] = {
- { "stream", SOCK_STREAM },
- { "dgram", SOCK_DGRAM },
+ { "stream", SOCK_STREAM },
+ { "dgram", SOCK_DGRAM },
{ "seqpacket", SOCK_SEQPACKET },
{ "raw", SOCK_RAW },
{ "rdm", SOCK_RDM },
@@ -820,12 +820,14 @@ static struct tokendef modetab[] = {
{"nostartaccept", pies_comp_inetd},
{"pass-fd", pies_comp_pass_fd},
{"pass", pies_comp_pass_fd},
+ {"startup", pies_comp_startup},
+ {"shutdown", pies_comp_shutdown},
{"boot", pies_comp_boot},
{"bootwait", pies_comp_boot},
{"powerfail", pies_comp_powerfail},
{"powerwait", pies_comp_powerwait},
{"powerokwait", pies_comp_powerokwait},
- {"ctrlaltdel", pies_comp_ctrlaltdel},
+ {"ctrlaltdel", pies_comp_ctrlaltdel},
{"ondemand", pies_comp_ondemand},
{"sysinit", pies_comp_sysinit},
{"powerfailnow", pies_comp_powerfailnow},
@@ -920,11 +922,11 @@ _cb_flags (enum grecs_callback_command cmd,
return 1;
}
break;
-
+
case GRECS_TYPE_LIST:
{
struct grecs_list_entry *ep;
-
+
for (ep = value->v.list->head; ep; ep = ep->next)
{
const grecs_value_t *vp = ep->data;
@@ -939,7 +941,7 @@ _cb_flags (enum grecs_callback_command cmd,
}
}
break;
-
+
case GRECS_TYPE_ARRAY:
grecs_error (locus, 0, _("too many arguments"));
return 1;
@@ -1228,7 +1230,7 @@ struct grecs_keyword *
find_component_keyword (const char *ident)
{
struct grecs_keyword *kwp;
-
+
for (kwp = component_keywords; kwp->ident; kwp++)
if (strcmp (kwp->ident, ident) == 0)
return kwp;
@@ -1256,7 +1258,7 @@ component_section_parser (enum grecs_callback_command cmd,
comp = *(struct component **) section_data;
component_finish (comp, locus);
break;
-
+
case grecs_callback_set_value:
grecs_error (locus, 0, _("expected block statement"));
}
@@ -1534,7 +1536,7 @@ pies_config_parse (char const *name)
if (!tree)
return 1;
-
+
for (node = tree; node; node = node->next)
{
node = grecs_find_node (node, "identity-provider");
@@ -1550,7 +1552,7 @@ pies_config_parse (char const *name)
if (grecs_error_count)
return 1;
-
+
return 0;
}
@@ -1573,7 +1575,7 @@ pies_read_config (void)
int err = 0;
component_config_begin ();
-
+
for (ep = config_list->head; ep; ep = ep->next)
{
struct config_file *file = ep->data;
@@ -1583,10 +1585,10 @@ pies_read_config (void)
if (init_process)
err = 0;
-
+
if (err)
component_config_rollback ();
-
+
return err;
}
@@ -1656,7 +1658,7 @@ setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc)
{
int i;
struct sigaction act;
-
+
act.sa_flags = 0;
sigemptyset (&act.sa_mask);
for (i = 0; i < sigc; i++)
@@ -1779,7 +1781,7 @@ request_restart_components (size_t cc, char **cv)
{
char **argv;
size_t i, j;
-
+
argv = grecs_calloc (5 + 3 * cc - 1, sizeof (*argv));
argv[0] = "piesctl";
argv[1] = "--url";
@@ -1803,7 +1805,7 @@ void
list_components (void)
{
char *argv[5];
-
+
argv[0] = "piesctl";
argv[1] = "--url";
argv[2] = (char*) pies_control_url ();
@@ -1942,7 +1944,7 @@ set_mailer_argcv (void)
{
int i;
struct wordsplit ws;
-
+
if (wordsplit (mailer_command_line, &ws, WRDSF_DEFFLAGS))
{
logmsg (LOG_CRIT, _("cannot parse mailer command line: %s"),
@@ -2033,7 +2035,7 @@ main (int argc, char **argv)
struct grecs_list_entry *ep;
int diag_flags;
int i;
-
+
set_program_name (argv[0]);
#ifdef ENABLE_NLS
setlocale (LC_ALL, "");
@@ -2043,10 +2045,10 @@ main (int argc, char **argv)
mf_proctitle_init (argc, argv, environ);
grecs_print_diag_fun = pies_diag_printer;
-
+
pies_master_argc = argc;
pies_master_argv = argv;
-
+
set_quoting_style (NULL, shell_quoting_style);
init_process = getpid () == 1;
@@ -2058,7 +2060,7 @@ main (int argc, char **argv)
break;
}
}
-
+
/* Set default logging */
if (init_process)
{
@@ -2067,13 +2069,13 @@ main (int argc, char **argv)
}
else
diag_flags = DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR);
-
+
diag_setup (diag_flags);
-
+
config_init ();
parse_options (&argc, &argv);
-
+
if (argc && !(command == COM_RESTART_COMPONENT
|| command == COM_TRACE_DEPEND
|| command == COM_TRACE_PREREQ))
@@ -2081,7 +2083,7 @@ main (int argc, char **argv)
logmsg (LOG_ERR, "extra command line arguments");
exit (EX_USAGE);
}
-
+
if (!instance)
{
instance = strrchr (program_name, '/');
@@ -2119,13 +2121,13 @@ main (int argc, char **argv)
set_state_file_names (instance);
set_mailer_argcv ();
-
+
if (lint_mode)
exit (0);
/* Re-setup logging: it might have been reset in the config file */
diag_setup (log_to_stderr_only ? DIAG_TO_STDERR : 0);
-
+
if (!control.url)
{
char const *str = default_control_url[init_process];
@@ -2137,7 +2139,7 @@ main (int argc, char **argv)
exit (EX_OSERR);
}
}
-
+
switch (command)
{
case COM_RESTART_COMPONENT:
@@ -2145,7 +2147,7 @@ main (int argc, char **argv)
if (pies_umask)
umask (pies_umask);
exit (request_restart_components (argc, argv));
-
+
case COM_RELOAD:
exit (request_reload ());
@@ -2162,11 +2164,11 @@ main (int argc, char **argv)
case COM_TRACE_DEPEND:
components_trace (argv, depmap_row);
exit (0);
-
- case COM_TRACE_PREREQ:
+
+ case COM_TRACE_PREREQ:
components_trace (argv, depmap_col);
exit (0);
-
+
default:
pies_priv_setup (&pies_privs);
if (pies_umask)
@@ -2193,13 +2195,13 @@ main (int argc, char **argv)
exit (EX_USAGE);
}
break;
-
+
case pies_status_running:
logmsg (LOG_ERR, _("another pies instance already running (pid %lu)"),
(unsigned long) pid);
exit (EX_USAGE);
}
-
+
if (!foreground)
{
check_pidfile (pidfile);
@@ -2212,14 +2214,14 @@ main (int argc, char **argv)
}
logmsg (LOG_INFO, _("%s %s starting"), proginfo.package, proginfo.version);
-
+
if (!init_process)
{
if (ctl_open ())
exit (EX_UNAVAILABLE);
create_pidfile (pidfile);
}
-
+
if (pies_master_argv[0][0] != '/')
logmsg (LOG_NOTICE,
_("not started as an absolute pathname; "
@@ -2228,6 +2230,7 @@ main (int argc, char **argv)
signal_setup (sig_handler);
progman_create_sockets ();
+ program_init_startup ();
progman_start ();
do
@@ -2261,7 +2264,7 @@ main (int argc, char **argv)
pies_schedule_children (PIES_CHLD_WAKEUP);
action = ACTION_CONT;
break;
-
+
case ACTION_STOP:
if (init_process)
{
@@ -2276,7 +2279,7 @@ main (int argc, char **argv)
pies_schedule_children (PIES_CHLD_WAKEUP);
action = ACTION_CONT;
break;
-
+
case ACTION_KBREQUEST:
debug (1, ("kbrequest"));
sysvinit_runlevel_setup (PIES_COMP_MASK (pies_comp_kbrequest));
diff --git a/src/pies.h b/src/pies.h
index a7f6567..bdc406b 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -104,7 +104,7 @@ struct action
enum return_action act; /* Action to take when the component terminates */
char *addr; /* Addresses to notify about it. */
char *message; /* Notification mail. */
- char *command; /* Execute this command */
+ char *command; /* Execute this command */
};
@@ -137,14 +137,21 @@ enum pies_comp_mode
component via the UNIX domain socket. Corresponds to
`start_action = pass' in MeTA1. */
pies_comp_pass_fd,
-
+
+ /* Components of this type runs once on program startup. Running other
+ components is delayed until the last startup component finishes. */
+ pies_comp_startup,
+
+ /* FIXME: Runs before program termination */
+ pies_comp_shutdown,
+
/*
** Init-style components
*/
pies_mark_sysvinit,
/* Start the process when the specified runlevel is entered and wait
for its termination */
- pies_comp_wait = pies_mark_sysvinit,
+ pies_comp_wait = pies_mark_sysvinit,
/* Execute the component once, when the specified runlevel is entered */
pies_comp_once,
/* Execute the component during system boot. Ignore runlevel settings. */
@@ -162,7 +169,7 @@ enum pies_comp_mode
pies_comp_powerokwait,
/* Execute the process when SIGINT is delivered, i.e. someone has
pressed the Ctrl+Alt+Del combination. */
- pies_comp_ctrlaltdel,
+ pies_comp_ctrlaltdel,
/* Execute the component when a specified ondemand runlevel is called */
pies_comp_ondemand,
/* Execute the component on the system boot. */
@@ -184,16 +191,16 @@ enum pies_comp_mode
#define CF_DISABLED 0x001 /* The componenet is disabled */
#define CF_PRECIOUS 0x002 /* The component is precious (should not
- be disabled) */
+ be disabled) */
#define CF_WAIT 0x004 /* Wait for the component instance to
- terminate. */
+ terminate. */
#define CF_TCPMUX 0x008 /* A plain TCPMUX service */
#define CF_TCPMUXPLUS 0x010 /* A TCPMUX-plus service, i.e. pies
- must emit a '+' response before starting
- it */
+ must emit a '+' response before starting
+ it */
#define CF_INTERNAL 0x020 /* An internal inetd service */
#define CF_SOCKENV 0x040 /* Component wants socket information in
- the environment */
+ the environment */
#define CF_RESOLVE 0x080 /* Resolve IP addresses */
#define CF_SIGGROUP 0x100 /* Send signals to the process group */
@@ -210,9 +217,9 @@ struct component
struct component *prev, *next; /* Components form doubly-linked list. */
int listidx; /* Index of the list. */
size_t arridx; /* Index of this component. */
- size_t ref_count; /* Reference count. */
+ size_t ref_count; /* Reference count. */
struct prog *prog; /* Prog associated with this component. */
-
+
enum pies_comp_mode mode;
char *tag; /* Entry tag (for diagnostics purposes) */
char *program; /* Program name */
@@ -232,7 +239,7 @@ struct component
/* For exec (init) components */
char *runlevels;
-
+
/* For inetd components */
size_t max_rate; /* Maximum number of invocations per minute */
size_t max_ip_connections; /* Max. number of connections per IP address */
@@ -253,9 +260,9 @@ struct component
char *access_denied_message;
char *max_instances_message;
char *max_ip_connections_message;
-
+
/* Redirectors: */
- int facility; /* Syslog facility. */
+ int facility; /* Syslog facility. */
struct redirector redir[2]; /* Repeaters for stdout and stderr */
/* Actions to execute on various exit codes: */
struct grecs_list *act_list;
@@ -334,6 +341,7 @@ int pies_read_config (void);
int pies_reread_config (void);
void register_prog (struct component *comp);
+void program_init_startup (void);
int progman_waiting_p (void);
void progman_start (void);
void progman_gc (void);
@@ -594,7 +602,7 @@ struct sysvinit_request
#define SYSV_ACCT_BOOT 0
#define SYSV_ACCT_RUNLEVEL 1
#define SYSV_ACCT_PROC_START 2
-#define SYSV_ACCT_PROC_STOP 3
+#define SYSV_ACCT_PROC_STOP 3
void sysvinit_acct (int what, const char *user, const char *id, pid_t pid,
const char *line);
diff --git a/src/progman.c b/src/progman.c
index 1b09cd5..5bc4eb3 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -65,7 +65,7 @@ progman_lookup_component (const char *tag)
if (IS_COMPONENT (prog) && strcmp (prog_tag (prog), tag) == 0)
return prog->v.p.comp;
return NULL;
-}
+}
struct component *
progman_lookup_tcpmux (const char *service, const char *master)
@@ -122,7 +122,7 @@ link_prog (struct prog *prog, struct prog *ref)
prog->prev = ref;
prog->next = ref->next;
-
+
if ((x = ref->next))
x->prev = prog;
else
@@ -151,21 +151,21 @@ void
destroy_prog (struct prog **pp)
{
struct prog *p = *pp;
-
+
unlink_prog (p);
switch (p->type)
{
case TYPE_COMPONENT:
component_ref_decr (p->v.p.comp);
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])
p->v.p.redir[RETR_OUT]->v.r.master = NULL;
if (p->v.p.redir[RETR_ERR])
p->v.p.redir[RETR_ERR]->v.r.master = NULL;
break;
-
+
case TYPE_REDIRECTOR:
{
struct prog *master = p->v.r.master;
@@ -182,7 +182,7 @@ destroy_prog (struct prog **pp)
free (p->v.r.tag);
}
break;
-
+
case TYPE_COMMAND:
free (p->v.c.tag);
free (p->v.c.command);
@@ -256,7 +256,7 @@ find_prog_ref (struct component *comp)
if (!comp)
return NULL; /* FIXME: Skip redirectors? */
}
-
+
if (comp->prog)
{
for (prog = comp->prog;
@@ -270,12 +270,12 @@ find_prog_ref (struct component *comp)
prog = NULL;
return prog;
}
-
+
static struct prog *
register_prog0 (struct component *comp)
{
struct prog *newp;
-
+
newp = grecs_zalloc (sizeof (*newp));
newp->type = TYPE_COMPONENT;
newp->pid = 0;
@@ -291,7 +291,7 @@ register_prog0 (struct component *comp)
newp->active = 0;
else
newp->active = 1;
-
+
if (comp->mode != pies_comp_exec)
comp->redir[RETR_OUT].type = redir_null;
@@ -317,14 +317,29 @@ register_command (char *tag, char *command, pid_t pid)
link_prog (newp, progtail);
}
+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
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))
{
debug (3, ("%s: waiting for %s (%lu)",
__FUNCTION__, prog_tag (prog),
@@ -406,17 +421,17 @@ open_redirector (struct prog *master, int stream)
case redir_file:
return redirect_to_file (master, stream);
-
+
case redir_syslog:
break;
}
-
+
if (pipe (p))
{
logmsg (LOG_CRIT, "pipe: %s", strerror (errno));
return -1;
}
-
+
switch (pid = fork ())
{
case 0:
@@ -428,10 +443,10 @@ open_redirector (struct prog *master, int stream)
FD_ZERO (&fdset);
FD_SET (p[0], &fdset);
close_fds (&fdset);
-
+
diag_setup (0);
signal_setup (redir_exit);
-
+
close (p[1]);
fp = fdopen (p[0], "r");
if (fp == NULL)
@@ -441,7 +456,7 @@ open_redirector (struct prog *master, int stream)
while (getline (&buf, &size, fp) > 0)
syslog (prio, "%s", buf);
_exit (0);
-
+
case -1:
logmsg (LOG_CRIT,
_("cannot run redirector `%s': fork failed: %s"),
@@ -466,7 +481,7 @@ conn_class_hasher (void *data, unsigned long n_buckets)
size_t value = 0;
unsigned char ch;
size_t len;
-
+
while ((ch = *tag++))
value = (value * 31 + ch) % n_buckets;
@@ -530,7 +545,7 @@ conn_class_lookup (const char *tag,
probe->sa_storage.s.sa_family);
break;
}
-
+
probe->count = 0;
if (!conn_tab)
{
@@ -725,7 +740,7 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
{
char *res;
size_t len;
-
+
if (a && b)
{
res = grecs_malloc (namelen + 1 + strlen (a) + strlen (b) + 1);
@@ -753,14 +768,14 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
res[namelen] = '=';
return res;
}
-
+
static void
environ_setup (char **hint)
{
char **old_env = environ;
char **new_env;
size_t count, i, j, n;
-
+
if (!hint)
return;
@@ -769,22 +784,22 @@ environ_setup (char **hint)
old_env = NULL;
hint++;
}
-
+
/* Count new environment size */
count = 0;
if (old_env)
for (i = 0; old_env[i]; i++)
count++;
-
+
for (i = 0; hint[i]; i++)
count++;
/* Allocate new environment. */
new_env = grecs_calloc (count + 1, sizeof new_env[0]);
-
+
/* Populate the environment. */
n = 0;
-
+
if (old_env)
for (i = 0; old_env[i]; i++)
{
@@ -795,7 +810,7 @@ environ_setup (char **hint)
for (i = 0; hint[i]; i++)
{
char *p;
-
+
if (hint[i][0] == '-')
{
/* Skip unset directives. */
@@ -806,12 +821,12 @@ environ_setup (char **hint)
slot if there's no such variable in new_env */
if (find_env_pos (new_env, hint[i], &j, NULL))
j = n;
-
+
if ((p = strchr (hint[i], '=')))
{
if (p == hint[i])
continue; /* Ignore erroneous entry */
- if (p[-1] == '+')
+ if (p[-1] == '+')
new_env[j] = env_concat (hint[i], p - hint[i] - 1,
find_env_ptr (environ, hint[i], 1),
p + 1);
@@ -835,7 +850,7 @@ environ_setup (char **hint)
if (envsize)
free (environ);
-
+
environ = new_env;
envsize = count + 1;
}
@@ -852,14 +867,14 @@ prog_sockenv (struct prog *prog)
union pies_sockaddr_storage *sa_client = &prog->v.p.sa_storage;
socklen_t cltlen = prog->v.p.sa_len;
const char *proto = NULL;
-
+
if (!(prog->v.p.comp->flags & CF_SOCKENV))
return;
if (socket_type_to_str (prog->v.p.comp->socket_type, &proto))
proto = umaxtostr (prog->v.p.comp->socket_type, buf);
add_env (ENV_SOCKTYPE, proto);
-
+
if (prog->v.p.comp->socket_url)
proto = prog->v.p.comp->socket_url->proto_s;
else if (prog->v.p.listener)
@@ -868,7 +883,7 @@ prog_sockenv (struct prog *prog)
proto = "TCP";
add_env (ENV_PROTO, proto);
-
+
if (getsockname (prog->v.p.socket,
(struct sockaddr *) &sa_server, &len) < 0)
logmsg (LOG_WARNING, "getsockname(): %s", strerror (errno));
@@ -920,7 +935,7 @@ static int
check_rate (struct prog *prog, unsigned testtime, size_t max_count)
{
time_t now;
-
+
time (&now);
if (prog->v.p.timestamp + testtime > now)
@@ -930,7 +945,7 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
prog->v.p.failcount = 0;
prog->v.p.timestamp = now;
}
-
+
if (prog->v.p.failcount > max_count)
{
prog->v.p.timestamp = now;
@@ -938,7 +953,7 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
return 1;
}
-
+
return 0;
}
@@ -961,7 +976,7 @@ static int
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))
{
logmsg (LOG_NOTICE,
@@ -1009,7 +1024,7 @@ prog_start_prologue (struct prog *prog)
logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"),