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

Make stop wait for the actual termination of the children processes #16

Merged
merged 12 commits into from
May 30, 2018
114 changes: 51 additions & 63 deletions lib/children.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "./gridinit-utils.h"
#include "./gridinit-internals.h"

time_t supervisor_default_delay_KILL = SUPERVISOR_DEFAULT_TIMEOUT_KILL;

static time_t _monotonic_seconds(void) {
return g_get_monotonic_time() / G_TIME_SPAN_SECOND;
}

/**
* Temporary flag used by gridinit to mark services during a refresh.
*/
Expand Down Expand Up @@ -90,6 +96,7 @@ struct my_rlimits_s {

struct child_s {
struct child_s *next;
time_t delay_before_KILL;
gchar *command;
pid_t pid;
uid_t uid;
Expand All @@ -99,9 +106,6 @@ struct child_s {
guint32 user_flags;
GSList *env;

gchar key[SUPERVISOR_LIMIT_CHILDKEYSIZE];
gchar group[2048];

/* Useful stats */
guint counter_started;
guint counter_died;
Expand All @@ -118,17 +122,13 @@ struct child_s {

/* Child's startup properties */
struct my_rlimits_s rlimits;
};

static struct child_s SRV_BEACON = {
NULL, NULL, 0, 0, 0,
NULL, 0, 0, NULL,
"", "", /* keys */
0, 0, 0, 0, 0, /* birth/death stats */
{0,0,0,0,0} /* deaths */,
{0,0,0} /* limits */
gchar key[SUPERVISOR_LIMIT_CHILDKEYSIZE];
gchar group[2048];
};

static struct child_s SRV_BEACON = {};

static supervisor_postfork_f *supervisor_cb_postfork = NULL;
static void *supervisor_cb_postfork_udata = NULL;

Expand Down Expand Up @@ -383,7 +383,7 @@ _child_start(struct child_s *sd, void *udata, supervisor_cb_f cb)
gint argc;
gchar **args;
struct my_rlimits_s saved_limits;

if (!sd || !sd->command) {
errno = EINVAL;
return -1;
Expand All @@ -393,10 +393,10 @@ _child_start(struct child_s *sd, void *udata, supervisor_cb_f cb)
errno = EINVAL;
return -1;
}

bzero(&saved_limits, sizeof(saved_limits));

sd->last_start_attempt = time(0);
sd->last_start_attempt = _monotonic_seconds();

_child_set_rlimits(&(sd->rlimits), &saved_limits);
sd->pid = fork();
Expand All @@ -415,7 +415,7 @@ _child_start(struct child_s *sd, void *udata, supervisor_cb_f cb)
if (supervisor_cb_postfork != NULL)
supervisor_cb_postfork(supervisor_cb_postfork_udata);
reset_sighandler();

/* change the rights before changing the working directory */
if (getuid() == 0) {
setgid(sd->gid);
Expand Down Expand Up @@ -458,14 +458,15 @@ static void
_child_stop(struct child_s *sd)
{
if (sd->pid > 0) {
time_t now = time(0);
time_t now = _monotonic_seconds();
if (sd->first_kill_attempt == 0)
sd->first_kill_attempt = now;
if (sd->first_kill_attempt > 0 && (now - sd->first_kill_attempt > SUPERVISOR_DEFAULT_TIMEOUT_KILL)) {
if (sd->delay_before_KILL > 0
&& sd->first_kill_attempt > 0
&& (now - sd->first_kill_attempt) > sd->delay_before_KILL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous 2 lines are indented with spaces.

DEBUG("Service [%s] did not exit after 60s, sending SIGKILL", sd->key);
kill(sd->pid, SIGKILL);
}
else {
} else {
DEBUG("Sending SIGTERM to service [%s] pid %i", sd->key, sd->pid);
kill(sd->pid, SIGTERM);
}
Expand All @@ -484,7 +485,7 @@ _child_notify_death(struct child_s *sd)
sd->deaths.t3 = sd->deaths.t2;
sd->deaths.t2 = sd->deaths.t1;
sd->deaths.t1 = sd->deaths.t0;
sd->deaths.t0 = time(0);
sd->deaths.t0 = _monotonic_seconds();

if (FLAG_HAS(sd, MASK_NEVER_BROKEN))
return;
Expand All @@ -505,7 +506,7 @@ _child_should_be_up(struct child_s *sd)
static void
_child_debug(struct child_s *sd, const gchar *tag)
{
time_t now = time(0);
time_t now = _monotonic_seconds();
DEBUG("%s [%s] flags=%04X now=%ld deaths{%ld,%ld,%ld,%ld,%ld}",
tag, sd->key, sd->flags, now,
now - sd->deaths.t0,
Expand All @@ -518,24 +519,22 @@ _child_debug(struct child_s *sd, const gchar *tag)
static gboolean
_child_can_be_restarted(struct child_s *sd)
{
time_t now;

if (!_child_should_be_up(sd))
return FALSE;

if (!sd->last_start_attempt)
if (!sd->last_start_attempt)
return TRUE;

/* here : already been started */
if (!FLAG_HAS(sd,MASK_RESPAWN))
return FALSE;

/* here : restart allowed */
if (!FLAG_HAS(sd,MASK_DELAYED))
if (!FLAG_HAS(sd,MASK_DELAYED))
return TRUE;

/* here : restart delayed if died too early */
now = time(0);
time_t now = _monotonic_seconds();

_child_debug(sd, "DEAD");

Expand Down Expand Up @@ -629,12 +628,6 @@ supervisor_children_start_enabled(void *udata, supervisor_cb_f cb)
return count;
}

guint
supervisor_children_startall(void *udata, supervisor_cb_f cb)
{
return supervisor_children_start_enabled(udata, cb);
}

guint
supervisor_children_mark_obsolete(void)
{
Expand Down Expand Up @@ -663,27 +656,7 @@ supervisor_children_disable_obsolete(void)
count ++;
}
}

return count;
}

guint
supervisor_children_kill_obsolete(void)
{
guint count;
struct child_s *sd;

count = 0U;

FOREACH_CHILD(sd) {
if (FLAG_HAS(sd,MASK_OBSOLETE)) {
if (sd->pid > 0) {
_child_stop(sd);
count ++;
}
}
}

return count;
}

Expand All @@ -694,7 +667,7 @@ supervisor_children_catharsis(void *udata, supervisor_cb_f cb)
guint count;
struct child_s *sd;
struct child_info_s ci;

count = 0;
while ((pid_dead = waitpid(-1, NULL, WNOHANG)) > 0) {
FOREACH_CHILD(sd) {
Expand Down Expand Up @@ -768,13 +741,11 @@ supervisor_children_fini(void)


gboolean
supervisor_children_register(const gchar *key, const gchar *cmd, GError **error)
supervisor_children_register(const gchar *key, const gchar *cmd)
{
struct child_s *sd = NULL;

(void) error;

/*check if the service is present*/
/* check if the service is present */
FOREACH_CHILD(sd) {
if (0 == g_ascii_strcasecmp(sd->key, key)) {

Expand All @@ -788,14 +759,15 @@ supervisor_children_register(const gchar *key, const gchar *cmd, GError **error)
}
}

/*Child not found, it will be created*/
/* Child not found, it will be created */
sd = g_try_malloc0(sizeof(struct child_s));
if (NULL == sd) {
errno = ENOMEM;
return FALSE;
}

g_strlcpy(sd->key, key, sizeof(sd->key)-1);
sd->delay_before_KILL = supervisor_default_delay_KILL;
sd->flags = MASK_STARTED|MASK_RESPAWN|MASK_DELAYED;
sd->working_directory = g_get_current_dir();
sd->command = g_strdup(cmd);
Expand All @@ -810,8 +782,8 @@ supervisor_children_register(const gchar *key, const gchar *cmd, GError **error)
(void) supervisor_limit_get(SUPERV_LIMIT_THREAD_STACK, &(sd->rlimits.stack_size));
(void) supervisor_limit_get(SUPERV_LIMIT_MAX_FILES, &(sd->rlimits.nb_files));
(void) supervisor_limit_get(SUPERV_LIMIT_CORE_SIZE, &(sd->rlimits.core_size));
/*ring insertion*/

/* ring insertion */
sd->next = SRV_BEACON.next;
SRV_BEACON.next = sd;

Expand Down Expand Up @@ -850,7 +822,7 @@ supervisor_children_kill_disabled(void)
FOREACH_CHILD(sd) {
/* Stop child that needs to be restarted */
if (FLAG_HAS(sd,MASK_RESTART))
_child_set_flag(sd, MASK_STARTED, FALSE);
_child_set_flag(sd, MASK_STARTED, FALSE);

if (!_child_should_be_up(sd)) {
if (sd->pid > 0) {
Expand All @@ -860,7 +832,7 @@ supervisor_children_kill_disabled(void)
}
}
}

return count;
}

Expand Down Expand Up @@ -943,7 +915,7 @@ supervisor_children_repair_all(void)
count ++;
}
}

errno = 0;
return count;
}
Expand Down Expand Up @@ -1166,6 +1138,22 @@ supervisor_children_set_ids(const gchar *key, gint32 uid, gint32 gid)
return 0;
}

int
supervisor_children_set_delay_sigkill(const char *key, time_t delay)
{
if (!key) {
errno = EINVAL;
return -1;
}
struct child_s *sd;
if (!(sd = supervisor_get_child(key))) {
errno = ENOENT;
return -1;
}
sd->delay_before_KILL = delay;
return 0;
}

void
supervisor_set_callback_postfork(supervisor_postfork_f *cb, void *udata)
{
Expand Down
1 change: 0 additions & 1 deletion lib/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

#include <glib.h>
Expand Down
Loading