Commit b75f4e1e authored by Martin Burnicki's avatar Martin Burnicki

[Bug 987] Wake up the resolver thread/process...

...when a new interface has become available.
parent d3a94678
* [Bug 987] Wake up the resolver thread/process when a new interface has become available.
* Correctly apply negative-sawtooth for oncore 12 channel receiver.
* Startup code for original LinuxPPS removed. LinuxPPS now conforms to
the PPSAPI.
......
......@@ -283,6 +283,11 @@ extern u_long numasyncmsgs; /* number of async messages we've sent */
/* ntp_intres.c */
extern keyid_t req_keyid; /* request keyid */
extern char * req_file; /* name of the file with configuration info */
#ifdef SYS_WINNT
extern HANDLE ResolverEventHandle;
#else
extern int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
#endif /* SYS_WINNT */
/*
* Other statistics of possible interest
......
......@@ -36,7 +36,10 @@
#ifdef SYS_WINNT
# include <io.h>
HANDLE ResolverThreadHandle = NULL;
static HANDLE ResolverThreadHandle = NULL;
HANDLE ResolverEventHandle;
#else
int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
#endif /* SYS_WINNT */
/*
......@@ -2432,7 +2435,22 @@ do_resolve_internal(void)
(void) signal_no_reset(SIGCHLD, catchchild);
#ifndef SYS_VXWORKS
/* the parent process will write to the pipe
* in order to wake up to child process
* which may be waiting in a select() call
* on the read fd */
if (pipe(resolver_pipe_fd) < 0) {
msyslog(LOG_ERR,
"unable to open resolver pipe");
exit(1);
}
i = fork();
/* Shouldn't the code below be re-ordered?
* I.e. first check if the fork() returned an error, then
* check whether we're parent or child.
* Martin Burnicki
*/
if (i == 0) {
/*
* this used to close everything
......@@ -2467,6 +2485,9 @@ do_resolve_internal(void)
* THUS:
*/
/* This is the child process who will read the pipe,
* so we close the write fd */
close(resolver_pipe_fd[1]);
closelog();
kill_asyncio(0);
......@@ -2515,6 +2536,11 @@ do_resolve_internal(void)
(void) signal_no_reset(SIGCHLD, SIG_DFL);
abort_resolve();
}
else {
/* This is the parent process who will write to the pipe,
* so we close the read fd */
close(resolver_pipe_fd[0]);
}
#else /* SYS_WINNT */
{
/* NT's equivalent of fork() is _spawn(), but the start point
......@@ -2523,6 +2549,11 @@ do_resolve_internal(void)
*/
DWORD dwThreadId;
fflush(stdout);
ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ResolverEventHandle == NULL) {
msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
abort_resolve();
}
ResolverThreadHandle = CreateThread(
NULL, /* no security attributes */
0, /* use default stack size */
......@@ -2532,6 +2563,8 @@ do_resolve_internal(void)
&dwThreadId); /* returns the thread identifier */
if (ResolverThreadHandle == NULL) {
msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
CloseHandle(ResolverEventHandle);
ResolverEventHandle = NULL;
abort_resolve();
}
}
......
......@@ -142,7 +142,6 @@ char *req_file; /* name of the file with configuration info */
/* end stuff to be filled in */
static RETSIGTYPE bong P((int));
static void checkparent P((void));
static void removeentry P((struct conf_entry *));
static void addentry P((char *, int, int, int, int, u_int,
......@@ -183,9 +182,11 @@ static void resolver_exit P((int));
static void resolver_exit (int code)
{
#ifdef SYS_WINNT
ExitThread (code); /* Just to kill the thread not the process */
CloseHandle(ResolverEventHandle);
ResolverEventHandle = NULL;
ExitThread(code); /* Just to kill the thread not the process */
#else
exit (code); /* fill the forked process */
exit(code); /* kill the forked process */
#endif
}
......@@ -215,11 +216,13 @@ void
ntp_intres(void)
{
FILE *in;
#ifdef HAVE_SIGSUSPEND
sigset_t set;
sigemptyset(&set);
#endif /* HAVE_SIGSUSPEND */
struct timeval tv;
fd_set fdset;
#ifdef SYS_WINNT
DWORD rc;
#else
int rc;
#endif
#ifdef DEBUG
if (debug > 1) {
......@@ -257,91 +260,81 @@ ntp_intres(void)
/*
* Sleep a little to make sure the server is completely up
*/
sleep(SLEEPTIME);
/*
* Make a first cut at resolving the bunch
* Set up the timers to do first try immediately.
*/
doconfigure(1);
if (confentries == NULL) {
resolver_exit(0);
}
/*
* Here we've got some problem children. Set up the timer
* and wait for it.
*/
resolve_value = resolve_timer = MINRESOLVE;
resolve_timer = 0;
resolve_value = MINRESOLVE;
config_timer = CONFIG_TIME;
#ifndef SYS_WINNT
(void) signal_no_reset(SIGALRM, bong);
alarm(ALARM_TIME);
#endif /* SYS_WINNT */
for (;;) {
if (confentries == NULL)
resolver_exit(0);
checkparent();
if (resolve_timer == 0) {
if (resolve_value < MAXRESOLVE)
resolve_value <<= 1;
doconfigure(1);
/* prepare retry, in case there's more work to do */
resolve_timer = resolve_value;
#ifdef DEBUG
if (debug > 2)
msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
#endif
if (resolve_value < MAXRESOLVE)
resolve_value <<= 1;
config_timer = CONFIG_TIME;
doconfigure(1);
continue;
} else if (config_timer == 0) {
} else if (config_timer == 0) { /* MB: in which case would this be required ? */
doconfigure(0);
/* MB: should we check now if we could exit, similar to the code above? */
config_timer = CONFIG_TIME;
#ifdef DEBUG
if (debug > 2)
msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
#endif
doconfigure(0);
continue;
}
#ifndef SYS_WINNT
/*
* There is a race in here. Is okay, though, since
* all it does is delay things by 30 seconds.
*/
# ifdef HAVE_SIGSUSPEND
sigsuspend(&set);
# else
sigpause(0);
# endif /* HAVE_SIGSUSPEND */
#else
if (confentries == NULL)
resolver_exit(0); /* done */
#ifdef SYS_WINNT
rc = WaitForSingleObject(ResolverEventHandle, 1000 * ALARM_TIME); /* in milliseconds */
if ( rc == WAIT_OBJECT_0 ) { /* signaled by the main thread */
resolve_timer = 0; /* retry resolving immediately */
continue;
}
if ( rc != WAIT_TIMEOUT ) /* not timeout: error */
resolver_exit(1);
#else /* not SYS_WINNT */
tv.tv_sec = ALARM_TIME;
tv.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(resolver_pipe_fd[0], &fdset);
rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
if (rc > 0) { /* parent process has written to the pipe */
read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc)); /* make pipe empty */
resolve_timer = 0; /* retry resolving immediately */
continue;
}
if ( rc < 0 ) /* select() returned error */
resolver_exit(1);
#endif
/* normal timeout, keep on waiting */
if (config_timer > 0)
config_timer--;
config_timer--;
if (resolve_timer > 0)
resolve_timer--;
sleep(ALARM_TIME);
#endif /* SYS_WINNT */
resolve_timer--;
}
}
#ifndef SYS_WINNT
/*
* bong - service and reschedule an alarm() interrupt
*/
static RETSIGTYPE
bong(
int sig
)
{
if (config_timer > 0)
config_timer--;
if (resolve_timer > 0)
resolve_timer--;
alarm(ALARM_TIME);
}
#endif /* SYS_WINNT */
/*
* checkparent - see if our parent process is still running
......@@ -1104,6 +1097,12 @@ doconfigure(
register struct conf_entry *ce;
register struct conf_entry *ceremove;
#ifdef DEBUG
if (debug > 1)
msyslog(LOG_INFO, "Running doconfigure %s DNS",
dores ? "with" : "without" );
#endif
ce = confentries;
while (ce != NULL) {
#ifdef DEBUG
......
......@@ -172,7 +172,7 @@ static u_char sys_interphase = 0;
static struct interface *new_interface P((struct interface *));
static void add_interface P((struct interface *));
static void update_interfaces P((u_short, interface_receiver_t, void *));
static int update_interfaces P((u_short, interface_receiver_t, void *));
static void remove_interface P((struct interface *));
static struct interface *create_interface P((u_short, struct interface *));
......@@ -1051,9 +1051,25 @@ void
interface_update(interface_receiver_t receiver, void *data)
{
if (!disable_dynamic_updates) {
int new_interface_found;
BLOCKIO();
update_interfaces(htons(NTP_PORT), receiver, data);
new_interface_found = update_interfaces(htons(NTP_PORT), receiver, data);
UNBLOCKIO();
if (new_interface_found) {
#ifdef DEBUG
msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
#endif
#ifdef SYS_WINNT
/* wake up the resolver thread */
if (ResolverEventHandle != NULL)
SetEvent(ResolverEventHandle);
#else
/* write any single byte to the pipe to wake up the resolver process */
write( resolver_pipe_fd[1], &new_interface_found, 1 );
#endif
}
}
}
......@@ -1146,7 +1162,7 @@ set_wildcard_reuse(int family, int on)
*
*/
static void
static int
update_interfaces(
u_short port,
interface_receiver_t receiver,
......@@ -1159,6 +1175,7 @@ update_interfaces(
isc_boolean_t scan_ipv4 = ISC_FALSE;
isc_boolean_t scan_ipv6 = ISC_FALSE;
isc_result_t result;
int new_interface_found = 0;
DPRINTF(3, ("update_interfaces(%d)\n", ntohs( (u_short) port)));
......@@ -1195,7 +1212,7 @@ update_interfaces(
result = isc_interfaceiter_create(mctx, &iter);
if (result != ISC_R_SUCCESS)
return;
return 0;
sys_interphase ^= 0x1; /* toggle system phase for finding untouched (to be deleted) interfaces */
......@@ -1298,6 +1315,8 @@ update_interfaces(
if (receiver)
receiver(data, &ifi);
new_interface_found = 1;
DPRINT_INTERFACE(3, (iface, "updating ", " new - created\n"));
}
else
......@@ -1371,8 +1390,9 @@ update_interfaces(
* phase 3 - re-configure as the world has changed if necessary
*/
refresh_all_peerinterfaces();
return new_interface_found;
}
/*
* create_sockets - create a socket for each interface plus a default
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment