kdc: add --testing option for leak testing

The kdc nowadays forks and restarts worker children.  This is nice, but
for leak checking in tests on OS X with leak(1) we really need the
worker to be the one process.
This commit is contained in:
Nicolas Williams
2016-12-06 16:40:51 -06:00
parent 87b234e154
commit 5f2e4fb368
3 changed files with 100 additions and 90 deletions

View File

@@ -52,6 +52,7 @@ static char *max_request_str; /* `max_request' as a string */
static int disable_des = -1;
static int builtin_hdb_flag;
int testing_flag;
static int help_flag;
static int version_flag;
@@ -120,6 +121,7 @@ static struct getargs args[] = {
{ "chroot", 0, arg_string, &chroot_string,
"chroot directory to run in", NULL
},
{ "testing", 0, arg_flag, &testing_flag, NULL, NULL },
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
{ "version", 'v', arg_flag, &version_flag, NULL, NULL }
};

View File

@@ -1153,109 +1153,115 @@ start_kdc(krb5_context context,
tv1.tv_usec = 0;
#ifdef HAVE_FORK
/* Note that we might never execute the body of this loop */
while (exit_flag == 0) {
if (!testing_flag) {
/* Note that we might never execute the body of this loop */
while (exit_flag == 0) {
/* Slow down the creation of KDCs... */
/* Slow down the creation of KDCs... */
gettimeofday(&tv2, NULL);
if (tv1.tv_sec == tv2.tv_sec && tv2.tv_usec - tv1.tv_usec < 25000) {
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");
kdc_log(context, config, 0, "Spawning KDCs too quickly, "
"pausing for 50ms");
#endif
select_sleep(12500);
continue;
}
select_sleep(12500);
continue;
}
if (num_kdcs >= max_kdcs) {
num_kdcs -= reap_kid(context, config, pids, max_kdcs, 0);
continue;
}
if (num_kdcs >= max_kdcs) {
num_kdcs -= reap_kid(context, config, pids, max_kdcs, 0);
continue;
}
if (num_kdcs > 0)
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs > 0)
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
pid = fork();
switch (pid) {
case 0:
close(islive[0]);
loop(context, config, d, ndescr, islive[1]);
exit(0);
case -1:
/* XXXrcd: hmmm, do something useful?? */
kdc_log(context, config, 0,
"KDC master process could not fork worker process");
sleep(10);
break;
default:
for (i=0; i < max_kdcs; i++) {
if (pids[i] == 0) {
pids[i] = pid;
break;
}
}
kdc_log(context, config, 0, "KDC worker process started: %d", pid);
num_kdcs++;
gettimeofday(&tv1, NULL);
break;
}
}
/* Closing these sockets should cause the kids to die... */
close(islive[0]);
close(islive[1]);
/* Close our listener sockets before terminating workers */
for (i = 0; i < ndescr; ++i)
clear_descr(&d[i]);
gettimeofday(&tv1, NULL);
tv2 = tv1;
/* Reap every 10ms, terminate stragglers once a second, give up after 10 */
for (;;) {
struct timeval tv3;
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0 && bonjour_pid <= 0)
goto end;
/*
* Using select to sleep will fail with EINTR if we receive a
* SIGCHLD. This is desirable.
*/
select_sleep(10000);
gettimeofday(&tv3, NULL);
if (tv3.tv_sec - tv1.tv_sec > 10 ||
(tv3.tv_sec - tv1.tv_sec == 10 && tv3.tv_usec >= tv1.tv_usec))
break;
if (tv3.tv_sec - tv2.tv_sec > 1 ||
(tv3.tv_sec - tv2.tv_sec == 1 && tv3.tv_usec >= tv2.tv_usec)) {
kill_kids(pids, max_kdcs, SIGTERM);
tv2 = tv3;
pid = fork();
switch (pid) {
case 0:
close(islive[0]);
loop(context, config, d, ndescr, islive[1]);
exit(0);
case -1:
/* XXXrcd: hmmm, do something useful?? */
kdc_log(context, config, 0,
"KDC master process could not fork worker process");
sleep(10);
break;
default:
for (i=0; i < max_kdcs; i++) {
if (pids[i] == 0) {
pids[i] = pid;
break;
}
}
kdc_log(context, config, 0, "KDC worker process started: %d",
pid);
num_kdcs++;
gettimeofday(&tv1, NULL);
break;
}
}
}
/* Kill stragglers and reap every 200ms, give up after 15s */
for (;;) {
kill_kids(pids, max_kdcs, SIGKILL);
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0 && bonjour_pid <= 0)
break;
select_sleep(200000);
gettimeofday(&tv2, NULL);
if (tv2.tv_sec - tv1.tv_sec > 15 ||
(tv2.tv_sec - tv1.tv_sec == 15 && tv2.tv_usec >= tv1.tv_usec))
break;
}
/* Closing these sockets should cause the kids to die... */
end:
kdc_log(context, config, 0, "KDC master process exiting", pid);
free(pids);
close(islive[0]);
close(islive[1]);
/* Close our listener sockets before terminating workers */
for (i = 0; i < ndescr; ++i)
clear_descr(&d[i]);
gettimeofday(&tv1, NULL);
tv2 = tv1;
/* Reap every 10ms, terminate stragglers once a second, give up after 10 */
for (;;) {
struct timeval tv3;
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0 && bonjour_pid <= 0)
goto end;
/*
* Using select to sleep will fail with EINTR if we receive a
* SIGCHLD. This is desirable.
*/
select_sleep(10000);
gettimeofday(&tv3, NULL);
if (tv3.tv_sec - tv1.tv_sec > 10 ||
(tv3.tv_sec - tv1.tv_sec == 10 && tv3.tv_usec >= tv1.tv_usec))
break;
if (tv3.tv_sec - tv2.tv_sec > 1 ||
(tv3.tv_sec - tv2.tv_sec == 1 && tv3.tv_usec >= tv2.tv_usec)) {
kill_kids(pids, max_kdcs, SIGTERM);
tv2 = tv3;
}
}
/* Kill stragglers and reap every 200ms, give up after 15s */
for (;;) {
kill_kids(pids, max_kdcs, SIGKILL);
num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0 && bonjour_pid <= 0)
break;
select_sleep(200000);
gettimeofday(&tv2, NULL);
if (tv2.tv_sec - tv1.tv_sec > 15 ||
(tv2.tv_sec - tv1.tv_sec == 15 && tv2.tv_usec >= tv1.tv_usec))
break;
}
end:
kdc_log(context, config, 0, "KDC master process exiting", pid);
free(pids);
} else {
loop(context, config, d, ndescr, -1);
kdc_log(context, config, 0, "KDC exiting", pid);
}
#else
loop(context, config, d, ndescr, -1);
kdc_log(context, config, 0, "KDC exiting", pid);
#endif
free (d);
free(d);
}

View File

@@ -103,6 +103,8 @@ extern int detach_from_console;
extern int daemon_child;
extern int do_bonjour;
extern int testing_flag;
extern const struct units _kdc_digestunits[];
#define KDC_LOG_FILE "kdc.log"