aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-24 18:34:29 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-11-24 18:34:29 +0200
commita7779d56bb758157e122a420a56f2d7b4475e554 (patch)
tree98241b97aa36b7713b2a76677b387cf214a1dbb7
parente6772c4d68849cfdb4547a59bc51cb6dd0acd2c6 (diff)
downloadpies-a7779d56bb758157e122a420a56f2d7b4475e554.tar.gz
pies-a7779d56bb758157e122a420a56f2d7b4475e554.tar.bz2
Implement inetd connection rate.
* src/pies.h (struct component): New member "max_rate". (default_max_rate): New extern. * src/progman.c (check_rate): New function. (check_spawn_rate, check_connection_rate): New functions. (prog_open_socket): New function. (prog_start): Rewrite using the above functions. (_prog_accept): Check connection rate. (progman_start): Special handling for inetd listeners. (progman_wake_sleeping): Likewise. * src/pies.c (default_max_rate): New global. (component_keywords): New keyword max-rate. (options): New option "rate". (parse_opt): Handle the new option. * src/inetd.c (inetd_conf_file): Set max_rate, instead of max_instances.
-rw-r--r--src/inetd.c6
-rw-r--r--src/pies.c24
-rw-r--r--src/pies.h6
-rw-r--r--src/progman.c178
4 files changed, 156 insertions, 58 deletions
diff --git a/src/inetd.c b/src/inetd.c
index ac40a5a..270425d 100644
--- a/src/inetd.c
+++ b/src/inetd.c
@@ -60,7 +60,7 @@ inetd_conf_file (const char *file)
struct component *comp;
int socket_type;
struct pies_url *url;
- size_t max_instances = 0;
+ size_t max_rate = 0;
int flags = 0;
char *str;
char *user = NULL;
@@ -161,7 +161,7 @@ inetd_conf_file (const char *file)
logmsg (LOG_WARNING, "%s:%lu: invalid number (near %s)",
file, line_no, p);
else
- max_instances = n;
+ max_rate = n;
}
if (strcmp (ws.ws_wordv[IFLD_WAIT], "wait") == 0)
@@ -199,7 +199,7 @@ inetd_conf_file (const char *file)
comp->mode = pies_comp_inetd;
comp->socket_type = socket_type;
comp->socket_url = url;
- comp->max_instances = max_instances;
+ comp->max_rate = max_rate;
comp->flags = flags;
comp->privs.user = xstrdup (user); /* FIXME: memory leak */
if (group)
diff --git a/src/pies.c b/src/pies.c
index fd83e04..74e71f7 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -34,6 +34,7 @@ char *ctlfile = LOCALSTATEDIR "/pies.ctl";
char *statfile = LOCALSTATEDIR "/pies.stat";
mode_t pies_umask = 0;
unsigned long shutdown_timeout = 5;
+size_t default_max_rate;
pies_acl_t pies_acl;
limits_record_t pies_limits;
int force_option;
@@ -900,6 +901,12 @@ struct grecs_keyword component_keywords[] = {
grecs_type_size, NULL,
offsetof (struct component, max_instances),
NULL },
+ {"max-rate",
+ NULL,
+ N_("Maximum number of times an inetd component can be invoked in one minute."),
+ grecs_type_size, NULL,
+ offsetof (struct component, max_rate),
+ NULL },
{"socket",
N_("url: string"),
N_("Listen on the given url."),
@@ -1389,7 +1396,8 @@ enum
OPT_DUMP_DEPMAP,
OPT_FORCE,
OPT_CONFIG_HELP,
- OPT_SOURCE_INFO
+ OPT_SOURCE_INFO,
+ OPT_RATE
};
#define OPT_RESTART 'R'
@@ -1415,6 +1423,9 @@ static struct argp_option options[] = {
N_("use FILE instead of the default configuration"), GRP + 1},
{"config-help", OPT_CONFIG_HELP, NULL, 0,
N_("show configuration file summary"), GRP + 1},
+ {"rate", OPT_RATE, N_("NUMBER"), 0,
+ N_("set default maximum rate for inetd-style components"),
+ GRP + 1},
#undef GRP
#define GRP 5
@@ -1455,6 +1466,8 @@ static struct argp_option options[] = {
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
+ char *p;
+
switch (key)
{
case 'c':
@@ -1513,6 +1526,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
debug_level = strtoul (arg, NULL, 0);
break;
+ case OPT_RATE:
+ default_max_rate = strtoul (arg, &p, 10);
+ if (*p)
+ {
+ logmsg (LOG_ERR, _("not a number: %s"), arg);
+ exit (EX_USAGE);
+ }
+ break;
+
case OPT_SOURCE_INFO:
source_info_option = 1;
break;
diff --git a/src/pies.h b/src/pies.h
index e387a56..5ba6ca7 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -153,7 +153,10 @@ struct component
gl_list_t prereq; /* Prerequisites */
gl_list_t depend; /* Dependency targets */
int flags; /* CF_ bitmask */
- size_t max_instances; /* Maximum number of running instances */
+ size_t max_instances; /* Maximum number of simultaneously running
+ instances (inetd) */
+ size_t max_rate; /* Maximum number of invocations per minute
+ (inetd) */
int socket_type; /* Socket type */
char *rmfile; /* Try to remove this file before starting */
struct pies_privs privs; /* UID/GIDS+groups to run under */
@@ -184,6 +187,7 @@ extern char *mailer_program;
extern char *mailer_command_line;
extern int mailer_argc;
extern char **mailer_argv;
+extern size_t default_max_rate;
void register_prog (struct component *comp);
size_t progman_running_count (void);
diff --git a/src/progman.c b/src/progman.c
index 227b438..f0cc4c9 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -610,11 +610,92 @@ env_setup (char **env)
return new_env;
}
+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)
+ prog->v.p.failcount++;
+ else
+ {
+ prog->v.p.failcount = 0;
+ prog->v.p.timestamp = now;
+ }
+
+ if (prog->v.p.failcount > max_count)
+ {
+ prog->v.p.timestamp = now;
+ prog->v.p.status = status_sleeping;
+ recompute_alarm = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+check_spawn_rate (struct prog *prog)
+{
+ if (check_rate (prog, TESTTIME, MAXSPAWN))
+ {
+ logmsg (LOG_NOTICE,
+ ngettext ("%s is respawning too fast, disabled for %d minute",
+ "%s is respawning too fast, disabled for %d minutes",
+ SLEEPTIME / 60),
+ prog->tag, SLEEPTIME / 60);
+ return 1;
+ }
+ return 0;
+}
+
+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;
+ if (max_rate && check_rate (prog, 60, max_rate))
+ {
+ logmsg (LOG_NOTICE,
+ ngettext ("%s is starting too often, disabled for %d minute",
+ "%s is starting too often, disabled for %d minutes",
+ SLEEPTIME / 60),
+ prog->tag, SLEEPTIME / 60);
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+prog_open_socket (struct prog *prog)
+{
+ prog->v.p.socket = create_socket (prog->v.p.comp->socket_url,
+ prog->v.p.comp->socket_type,
+ prog->v.p.comp->privs.user,
+ prog->v.p.comp->umask);
+ if (prog->v.p.socket == -1)
+ {
+ prog->v.p.status = status_disabled;
+ return 1;
+ }
+ if (listen (prog->v.p.socket, 8))
+ {
+ logmsg (LOG_ERR, "listen: %s", strerror (errno));
+ close (prog->v.p.socket);
+ prog->v.p.socket = -1;
+ prog->v.p.status = status_disabled;
+ return 1;
+ }
+ return 0;
+}
+
static void
prog_start (struct prog *prog)
{
pid_t pid;
- time_t now;
int redir[2];
fd_set fdset;
@@ -629,35 +710,16 @@ prog_start (struct prog *prog)
if (prog_start_prerequisites (prog))
return;
- time (&now);
-
- if (prog->v.p.timestamp + TESTTIME > now)
- prog->v.p.failcount++;
- else
- {
- prog->v.p.failcount = 0;
- prog->v.p.timestamp = now;
- }
-
- if (prog->v.p.failcount > MAXSPAWN)
- {
- logmsg (LOG_NOTICE, ngettext (
- "%s is respawning too fast, disabled for %d minute",
- "%s is respawning too fast, disabled for %d minutes",
- SLEEPTIME / 60),
- prog->tag, SLEEPTIME / 60);
- prog->v.p.timestamp = now;
- prog->v.p.status = status_sleeping;
- recompute_alarm = 1;
- return;
- }
-
switch (prog->v.p.comp->mode)
{
case pies_comp_exec:
+ if (check_spawn_rate (prog))
+ return;
break;
case pies_comp_pass_fd:
+ if (check_spawn_rate (prog))
+ return;
debug (1, (_("unlinking %s"), prog->v.p.comp->pass_fd_socket));
if (unlink (prog->v.p.comp->pass_fd_socket) && errno != ENOENT)
{
@@ -666,26 +728,15 @@ prog_start (struct prog *prog)
strerror (errno));
return;
}
- /* fall through */
+ if (prog_open_socket (prog))
+ return;
+ break;
case pies_comp_accept:
- prog->v.p.socket = create_socket (prog->v.p.comp->socket_url,
- prog->v.p.comp->socket_type,
- prog->v.p.comp->privs.user,
- prog->v.p.comp->umask);
- if (prog->v.p.socket == -1)
- {
- prog->v.p.status = status_disabled;
- return;
- }
- if (listen (prog->v.p.socket, 8))
- {
- logmsg (LOG_ERR, "listen: %s", strerror (errno));
- close (prog->v.p.socket);
- prog->v.p.socket = -1;
- prog->v.p.status = status_disabled;
- return;
- }
+ if (check_spawn_rate (prog))
+ return;
+ if (prog_open_socket (prog))
+ return;
break;
case pies_comp_inetd:
@@ -897,6 +948,13 @@ _prog_accept (struct prog *p)
close (fd);
return 1;
}
+
+ if (check_connection_rate (p))
+ {
+ disable_socket (p->v.p.socket);
+ close (fd);
+ return 1;
+ }
pinst = register_prog0 (p->v.p.comp, -1);
pinst->v.p.socket = fd;
@@ -1192,10 +1250,17 @@ progman_start ()
recompute_alarm = 0;
debug (1, ("starting components"));
for (prog = proghead; prog; prog = prog->next)
- if (IS_COMPONENT (prog)
- && ((prog->v.p.status == status_enabled && prog->pid == 0)
- || prog->v.p.status == status_sleeping))
- prog_start (prog);
+ if (IS_COMPONENT (prog))
+ {
+ if (prog->v.p.comp->mode == pies_comp_inetd)
+ {
+ prog->v.p.status = status_listener;
+ enable_socket (prog->v.p.socket);
+ }
+ else if ((prog->v.p.status == status_enabled && prog->pid == 0)
+ || prog->v.p.status == status_sleeping)
+ prog_start (prog);
+ }
}
static void
@@ -1230,10 +1295,18 @@ progman_wake_sleeping (int onalrm)
case status_sleeping:
if (now - prog->v.p.timestamp >= SLEEPTIME)
{
- prog->v.p.status = status_enabled;
- prog->v.p.failcount = 0;
- prog->v.p.timestamp = 0;
- prog_start (prog);
+ if (prog->v.p.comp->mode == pies_comp_inetd)
+ {
+ prog->v.p.status = status_listener;
+ enable_socket (prog->v.p.socket);
+ }
+ else
+ {
+ prog->v.p.status = status_enabled;
+ prog->v.p.failcount = 0;
+ prog->v.p.timestamp = 0;
+ prog_start (prog);
+ }
}
/* If there is no alarm pending, recompute next alarm.
This allows to cope with eventual clock inaccuracies. */
@@ -1882,9 +1955,8 @@ progman_stop_component (const char *name)
default:
logmsg (LOG_INFO,
- _("stopping component `%s': "
- "component not started"),
- name);
+ _("stopping component `%s': component not started"),
+ name);
}
}
}

Return to:

Send suggestions and report system problems to the System administrator.