MacOS/X fixes

This commit is contained in:
Viktor Dukhovni
2016-05-22 16:59:25 -04:00
parent ffd0dda237
commit 529a91d69a
6 changed files with 102 additions and 37 deletions

View File

@@ -102,6 +102,12 @@ static struct getargs args[] = {
"daemon-child", 0 , arg_flag, &daemon_child, "daemon-child", 0 , arg_flag, &daemon_child,
"private argument, do not use", NULL "private argument, do not use", NULL
}, },
#ifdef __APPLE__
{
"bonjour", 0 , arg_flag, &do_bonjour,
"private argument, do not use", NULL
},
#endif
{ "addresses", 0, arg_strings, &addresses_str, { "addresses", 0, arg_strings, &addresses_str,
"addresses to listen on", "list of addresses" }, "addresses to listen on", "list of addresses" },
{ "disable-des", 0, arg_flag, &disable_des, { "disable-des", 0, arg_flag, &disable_des,

View File

@@ -47,6 +47,7 @@ struct port_desc{
static struct port_desc *ports; static struct port_desc *ports;
static size_t num_ports; static size_t num_ports;
static pid_t bonjour_pid = -1;
/* /*
* add `family, port, protocol' to the list with duplicate suppresion. * add `family, port, protocol' to the list with duplicate suppresion.
@@ -258,6 +259,7 @@ init_socket(krb5_context context,
d->s = rk_INVALID_SOCKET; d->s = rk_INVALID_SOCKET;
return; return;
} }
rk_cloexec(d->s);
#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR) #if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR)
{ {
int one = 1; int one = 1;
@@ -833,11 +835,11 @@ handle_tcp(krb5_context context,
static void static void
handle_islive(int fd) handle_islive(int fd)
{ {
char buf[2]; char buf;
int ret; int ret;
ret = read(fd, buf, 2); ret = read(fd, &buf, 1);
if (ret == 0) if (ret != 1)
exit_flag = -1; exit_flag = -1;
} }
#endif #endif
@@ -971,17 +973,28 @@ loop(krb5_context context, krb5_kdc_configuration *config,
#ifdef __APPLE__ #ifdef __APPLE__
static void static void
bonjour_kid(krb5_context context, krb5_kdc_configuration *config, int islive) bonjour_kid(krb5_context context, krb5_kdc_configuration *config, const char *argv0, int *islive)
{ {
char buf[2]; char buf;
if (fork()) if (do_bonjour > 0) {
bonjour_announce(context, config);
while (read(0, &buf, 1) == 1)
continue;
_exit(0);
}
if ((bonjour_pid = fork()) != 0)
return; return;
bonjour_announce(context, config);
while (read(islive, buf, 1) != 0) close(islive[0]);
; if (dup2(islive[1], 0) == -1)
exit(0); err(1, "failed to announce with bonjour (dup)");
if (islive[1] != 0)
close(islive[1]);
execlp(argv0, "kdc", "--bonjour", NULL);
err(1, "failed to announce with bonjour (exec)");
} }
#endif #endif
@@ -994,6 +1007,8 @@ kill_kids(pid_t *pids, int max_kids, int sig)
for (i=0; i < max_kids; i++) for (i=0; i < max_kids; i++)
if (pids[i] > 0) if (pids[i] > 0)
kill(sig, pids[i]); kill(sig, pids[i]);
if (bonjour_pid > 0)
kill(sig, bonjour_pid);
} }
static int static int
@@ -1001,6 +1016,7 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config,
pid_t *pids, int max_kids, int options) pid_t *pids, int max_kids, int options)
{ {
pid_t pid; pid_t pid;
char *what;
int status; int status;
int i; int i;
@@ -1008,21 +1024,39 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config,
if (pid < 1) if (pid < 1)
return 0; return 0;
for (i=0; i < max_kids; i++) { if (pid != bonjour_pid) {
if (pids[i] == pid) for (i=0; i < max_kids; i++) {
break; if (pids[i] == pid)
break;
}
if (i == max_kids) {
/* XXXrcd: this should not happen, have to do something, though */
return 0;
}
} }
if (i == max_kids) { if (pid == bonjour_pid)
/* XXXrcd: this should not happen, have to do something, though */ what = "bonjour";
return 0; else
what = "worker";
if (WIFEXITED(status))
kdc_log(context, config, 0, "KDC reaped %s process: %d, exit status: %d",
what, (int)pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
kdc_log(context, config, 0, "KDC reaped %s process: %d, term signal %d%s",
what, (int)pid, WTERMSIG(status),
WCOREDUMP(status) ? " (core dumped)" : "");
else
kdc_log(context, config, 0, "KDC reaped %s process: %d",
what, (int)pid);
if (pid == bonjour_pid) {
bonjour_pid = (pid_t)-1;
return 0;
} else {
pids[i] = (pid_t)-1;
return 1;
} }
/* XXXrcd: should likely log exit code and the like */
kdc_log(context, config, 0, "KDC worker process reaped: %d", pid);
pids[i] = (pid_t)-1;
return 1;
} }
static int static int
@@ -1053,7 +1087,7 @@ select_sleep(int microseconds)
void void
start_kdc(krb5_context context, start_kdc(krb5_context context,
krb5_kdc_configuration *config) krb5_kdc_configuration *config, const char *argv0)
{ {
struct timeval tv1; struct timeval tv1;
struct timeval tv2; struct timeval tv2;
@@ -1068,6 +1102,11 @@ start_kdc(krb5_context context,
int islive[2]; int islive[2];
#endif #endif
#ifdef __APPLE__
if (do_bonjour > 0)
bonjour_kid(context, config, argv0, NULL);
#endif
#ifdef HAVE_FORK #ifdef HAVE_FORK
#ifdef _SC_NPROCESSORS_ONLN #ifdef _SC_NPROCESSORS_ONLN
if (max_kdcs < 1) if (max_kdcs < 1)
@@ -1099,9 +1138,10 @@ start_kdc(krb5_context context,
#ifdef HAVE_FORK #ifdef HAVE_FORK
#ifdef __APPLE__ # ifdef __APPLE__
bonjour_kid(context, config, islive[1]); /* fork()s */ if (do_bonjour < 0)
#endif bonjour_kid(context, config, argv0, islive);
# endif
kdc_log(context, config, 0, "KDC started master process pid=%d", getpid()); kdc_log(context, config, 0, "KDC started master process pid=%d", getpid());
#else #else
@@ -1165,34 +1205,49 @@ start_kdc(krb5_context context,
close(islive[0]); close(islive[0]);
close(islive[1]); close(islive[1]);
gettimeofday(&tv1, NULL); /* 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 (;;) { for (;;) {
struct timeval tv3;
num_kdcs -= reap_kids(context, config, pids, max_kdcs); num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0) if (num_kdcs == 0 && bonjour_pid <= 0)
break; goto end;
/* /*
* Using select to sleep will fail with EINTR if we receive a * Using select to sleep will fail with EINTR if we receive a
* SIGCHLD. This is desirable. * SIGCHLD. This is desirable.
*/ */
select_sleep(200000); select_sleep(10000);
kill_kids(pids, max_kdcs, SIGTERM); gettimeofday(&tv3, NULL);
gettimeofday(&tv2, NULL); if (tv3.tv_sec - tv1.tv_sec > 10 ||
if (tv2.tv_sec - tv1.tv_sec > 10) (tv3.tv_sec - tv1.tv_sec == 10 && tv3.tv_usec >= tv1.tv_usec))
break; 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 (;;) { for (;;) {
kill_kids(pids, max_kdcs, SIGKILL); kill_kids(pids, max_kdcs, SIGKILL);
num_kdcs -= reap_kids(context, config, pids, max_kdcs); num_kdcs -= reap_kids(context, config, pids, max_kdcs);
if (num_kdcs == 0) if (num_kdcs == 0 && bonjour_pid <= 0)
break; break;
select_sleep(200000); select_sleep(200000);
gettimeofday(&tv2, NULL); gettimeofday(&tv2, NULL);
if (tv2.tv_sec - tv1.tv_sec > 15) if (tv2.tv_sec - tv1.tv_sec > 15 ||
(tv2.tv_sec - tv1.tv_sec == 15 && tv2.tv_usec >= tv1.tv_usec))
break; break;
} }
end:
kdc_log(context, config, 0, "KDC master process exiting", pid); kdc_log(context, config, 0, "KDC master process exiting", pid);
free(pids); free(pids);
#else #else

View File

@@ -46,6 +46,7 @@ struct perf {
int detach_from_console = -1; int detach_from_console = -1;
int daemon_child = -1; int daemon_child = -1;
int do_bonjour = -1;
static krb5_kdc_configuration *kdc_config; static krb5_kdc_configuration *kdc_config;
static krb5_context kdc_context; static krb5_context kdc_context;

View File

@@ -101,6 +101,7 @@ extern int enable_http;
extern int detach_from_console; extern int detach_from_console;
extern int daemon_child; extern int daemon_child;
extern int do_bonjour;
extern const struct units _kdc_digestunits[]; extern const struct units _kdc_digestunits[];
@@ -113,7 +114,7 @@ extern char *runas_string;
extern char *chroot_string; extern char *chroot_string;
void void
start_kdc(krb5_context context, krb5_kdc_configuration *config); start_kdc(krb5_context context, krb5_kdc_configuration *config, const char *argv0);
krb5_kdc_configuration * krb5_kdc_configuration *
configure(krb5_context context, int argc, char **argv, int *optidx); configure(krb5_context context, int argc, char **argv, int *optidx);

View File

@@ -46,6 +46,7 @@ sig_atomic_t exit_flag = 0;
int detach_from_console = -1; int detach_from_console = -1;
int daemon_child = -1; int daemon_child = -1;
int do_bonjour = -1;
static RETSIGTYPE static RETSIGTYPE
sigchld(int sig) sigchld(int sig)
@@ -172,7 +173,7 @@ main(int argc, char **argv)
switch_environment(); switch_environment();
start_kdc(context, config); start_kdc(context, config, argv[0]);
krb5_free_context(context); krb5_free_context(context);
return 0; return 0;
} }

View File

@@ -50,6 +50,7 @@
#endif #endif
#include <evp.h> #include <evp.h>
#include <evp-hcrypto.h>
#include <evp-cc.h> #include <evp-cc.h>
/* /*