+* [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.
/* 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
#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 */
/*
(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
* 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);
(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
*/
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 */
&dwThreadId); /* returns the thread identifier */
if (ResolverThreadHandle == NULL) {
msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
+ CloseHandle(ResolverEventHandle);
+ ResolverEventHandle = NULL;
abort_resolve();
}
}
/* 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,
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
}
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) {
/*
* 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
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
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 *));
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
+ }
}
}
*
*/
-static void
+static int
update_interfaces(
u_short port,
interface_receiver_t receiver,
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)));
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 */
if (receiver)
receiver(data, &ifi);
+ new_interface_found = 1;
+
DPRINT_INTERFACE(3, (iface, "updating ", " new - created\n"));
}
else
* 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