Further improve kdc child process management
- Simplify child process creation rate limit by moving select_sleep() to happen right after the parent fork(). - Consider child pid table slots to be empty if the pid is non-positive, rather than just -1 or just 0. - Log warnings should we ever spawn a child with no free slot to track it, or reap a child that does not match a tracked slot.
This commit is contained in:

committed by
Jeffrey Altman

parent
3bcc031939
commit
e014662651
@@ -1025,44 +1025,49 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config,
|
|||||||
char *what;
|
char *what;
|
||||||
int status;
|
int status;
|
||||||
int i = 0; /* quiet warnings */
|
int i = 0; /* quiet warnings */
|
||||||
|
int ret = 0;
|
||||||
|
int level = 0;
|
||||||
|
const char *sev = "";
|
||||||
|
|
||||||
pid = waitpid(-1, &status, options);
|
pid = waitpid(-1, &status, options);
|
||||||
if (pid < 1)
|
if (pid <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (pid != bonjour_pid) {
|
if (pid == bonjour_pid) {
|
||||||
|
bonjour_pid = (pid_t)-1;
|
||||||
|
what = "bonjour";
|
||||||
|
} else {
|
||||||
for (i=0; i < max_kids; i++) {
|
for (i=0; i < max_kids; i++) {
|
||||||
if (pids[i] == pid)
|
if (pids[i] == pid) {
|
||||||
|
pids[i] = (pid_t)-1;
|
||||||
|
what = "worker";
|
||||||
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == max_kids) {
|
if (i == max_kids) {
|
||||||
/* XXXrcd: this should not happen, have to do something, though */
|
/* should not happen */
|
||||||
return 0;
|
what = "untracked";
|
||||||
|
sev = "warning: ";
|
||||||
|
level = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == bonjour_pid)
|
|
||||||
what = "bonjour";
|
|
||||||
else
|
|
||||||
what = "worker";
|
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
kdc_log(context, config, 0, "KDC reaped %s process: %d, exit status: %d",
|
kdc_log(context, config, level,
|
||||||
what, (int)pid, WEXITSTATUS(status));
|
"%sKDC reaped %s process: %d, exit status: %d",
|
||||||
|
sev, what, (int)pid, WEXITSTATUS(status));
|
||||||
else if (WIFSIGNALED(status))
|
else if (WIFSIGNALED(status))
|
||||||
kdc_log(context, config, 0, "KDC reaped %s process: %d, term signal %d%s",
|
kdc_log(context, config, level,
|
||||||
what, (int)pid, WTERMSIG(status),
|
"%sKDC reaped %s process: %d, term signal %d%s",
|
||||||
|
sev, what, (int)pid, WTERMSIG(status),
|
||||||
WCOREDUMP(status) ? " (core dumped)" : "");
|
WCOREDUMP(status) ? " (core dumped)" : "");
|
||||||
else
|
else
|
||||||
kdc_log(context, config, 0, "KDC reaped %s process: %d",
|
kdc_log(context, config, level, "%sKDC reaped %s process: %d",
|
||||||
what, (int)pid);
|
sev, what, (int)pid);
|
||||||
if (pid == bonjour_pid) {
|
|
||||||
bonjour_pid = (pid_t)-1;
|
return ret;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
pids[i] = (pid_t)-1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1122,11 +1127,9 @@ start_kdc(krb5_context context,
|
|||||||
if (max_kdcs < 1)
|
if (max_kdcs < 1)
|
||||||
max_kdcs = 1;
|
max_kdcs = 1;
|
||||||
|
|
||||||
pids = malloc(max_kdcs * sizeof(*pids));
|
pids = calloc(max_kdcs, sizeof(*pids));
|
||||||
if (!pids)
|
if (pids == NULL)
|
||||||
krb5_err(context, 1, errno, "malloc");
|
krb5_err(context, 1, errno, "malloc");
|
||||||
for (i = 0; i < max_kdcs; i++)
|
|
||||||
pids[i] = (pid_t)-1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We open a socketpair of which we hand one end to each of our kids.
|
* We open a socketpair of which we hand one end to each of our kids.
|
||||||
@@ -1157,26 +1160,11 @@ start_kdc(krb5_context context,
|
|||||||
|
|
||||||
roken_detach_finish(NULL, daemon_child);
|
roken_detach_finish(NULL, daemon_child);
|
||||||
|
|
||||||
tv1.tv_sec = 0;
|
|
||||||
tv1.tv_usec = 0;
|
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
if (!testing_flag) {
|
if (!testing_flag) {
|
||||||
/* Note that we might never execute the body of this loop */
|
/* Note that we might never execute the body of this loop */
|
||||||
while (exit_flag == 0) {
|
while (exit_flag == 0) {
|
||||||
|
|
||||||
/* Slow down the creation of KDCs... */
|
|
||||||
|
|
||||||
gettimeofday(&tv2, NULL);
|
|
||||||
if (tv1.tv_sec == tv2.tv_sec && tv2.tv_usec - tv1.tv_usec < 25000) {
|
|
||||||
#if 0 /* XXXrcd: should print a message... */
|
|
||||||
kdc_log(context, config, 0, "Spawning KDCs too quickly, "
|
|
||||||
"pausing for 50ms");
|
|
||||||
#endif
|
|
||||||
select_sleep(12500);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_kdcs >= max_kdcs) {
|
if (num_kdcs >= max_kdcs) {
|
||||||
num_kdcs -= reap_kid(context, config, pids, max_kdcs, 0);
|
num_kdcs -= reap_kid(context, config, pids, max_kdcs, 0);
|
||||||
continue;
|
continue;
|
||||||
@@ -1199,15 +1187,22 @@ start_kdc(krb5_context context,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for (i = 0; i < max_kdcs; i++) {
|
for (i = 0; i < max_kdcs; i++) {
|
||||||
if (pids[i] == (pid_t)-1) {
|
if (pids[i] <= 0) {
|
||||||
pids[i] = pid;
|
pids[i] = pid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i >= max_kdcs) {
|
||||||
|
/* This should not happen */
|
||||||
|
kdc_log(context, config, 1,
|
||||||
|
"warning: forked untracked child process: %d",
|
||||||
|
(int)pid);
|
||||||
|
}
|
||||||
kdc_log(context, config, 0, "KDC worker process started: %d",
|
kdc_log(context, config, 0, "KDC worker process started: %d",
|
||||||
pid);
|
pid);
|
||||||
num_kdcs++;
|
num_kdcs++;
|
||||||
gettimeofday(&tv1, NULL);
|
/* Slow down the creation of KDCs... */
|
||||||
|
select_sleep(12500);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user