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 disable_des = -1;
static int builtin_hdb_flag; static int builtin_hdb_flag;
int testing_flag;
static int help_flag; static int help_flag;
static int version_flag; static int version_flag;
@@ -120,6 +121,7 @@ static struct getargs args[] = {
{ "chroot", 0, arg_string, &chroot_string, { "chroot", 0, arg_string, &chroot_string,
"chroot directory to run in", NULL "chroot directory to run in", NULL
}, },
{ "testing", 0, arg_flag, &testing_flag, NULL, NULL },
{ "help", 'h', arg_flag, &help_flag, NULL, NULL }, { "help", 'h', arg_flag, &help_flag, NULL, NULL },
{ "version", 'v', arg_flag, &version_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; tv1.tv_usec = 0;
#ifdef HAVE_FORK #ifdef HAVE_FORK
/* Note that we might never execute the body of this loop */ if (!testing_flag) {
while (exit_flag == 0) { /* 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); gettimeofday(&tv2, NULL);
if (tv1.tv_sec == tv2.tv_sec && tv2.tv_usec - tv1.tv_usec < 25000) { if (tv1.tv_sec == tv2.tv_sec && tv2.tv_usec - tv1.tv_usec < 25000) {
#if 0 /* XXXrcd: should print a message... */ #if 0 /* XXXrcd: should print a message... */
kdc_log(context, config, 0, "Spawning KDCs too quickly, " kdc_log(context, config, 0, "Spawning KDCs too quickly, "
"pausing for 50ms"); "pausing for 50ms");
#endif #endif
select_sleep(12500); select_sleep(12500);
continue; 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;
} }
if (num_kdcs > 0) if (num_kdcs > 0)
num_kdcs -= reap_kids(context, config, pids, max_kdcs); num_kdcs -= reap_kids(context, config, pids, max_kdcs);
pid = fork(); pid = fork();
switch (pid) { switch (pid) {
case 0: case 0:
close(islive[0]); close(islive[0]);
loop(context, config, d, ndescr, islive[1]); loop(context, config, d, ndescr, islive[1]);
exit(0); exit(0);
case -1: case -1:
/* XXXrcd: hmmm, do something useful?? */ /* XXXrcd: hmmm, do something useful?? */
kdc_log(context, config, 0, kdc_log(context, config, 0,
"KDC master process could not fork worker process"); "KDC master process could not fork worker process");
sleep(10); sleep(10);
break; break;
default: default:
for (i=0; i < max_kdcs; i++) { for (i=0; i < max_kdcs; i++) {
if (pids[i] == 0) { if (pids[i] == 0) {
pids[i] = pid; pids[i] = pid;
break; break;
} }
} }
kdc_log(context, config, 0, "KDC worker process started: %d", pid); kdc_log(context, config, 0, "KDC worker process started: %d",
num_kdcs++; pid);
gettimeofday(&tv1, NULL); num_kdcs++;
break; 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;
} }
}
/* Kill stragglers and reap every 200ms, give up after 15s */ /* Closing these sockets should cause the kids to die... */
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: close(islive[0]);
kdc_log(context, config, 0, "KDC master process exiting", pid); close(islive[1]);
free(pids);
/* 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 #else
loop(context, config, d, ndescr, -1); loop(context, config, d, ndescr, -1);
kdc_log(context, config, 0, "KDC exiting", pid); kdc_log(context, config, 0, "KDC exiting", pid);
#endif #endif
free (d); free(d);
} }

View File

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