#include <stdio.h>
#include <ctype.h>
+#include <signal.h>
#ifndef SYS_WINNT
#include <pthread.h>
#endif
#else
void * blocking_thread(void *);
#endif
+#ifndef SYS_WINNT
+static void block_thread_signals(sigset_t *);
+#endif
void
int is_pipe;
int flags;
size_t stacksize;
+ sigset_t saved_sig_mask;
# ifdef NEED_PTHREAD_INIT
/*
pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
#endif
c->thread_ref = emalloc_zero(sizeof(*c->thread_ref));
+ block_thread_signals(&saved_sig_mask);
rc = pthread_create(c->thread_ref, &thr_attr,
&blocking_thread, c);
saved_errno = errno;
+ pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
pthread_attr_destroy(&thr_attr);
if (0 != rc) {
errno = saved_errno;
}
#endif
+
+/*
+ * block_thread_signals()
+ *
+ * Temporarily block signals used by ntpd main thread, so that signal
+ * mask inherited by child threads leaves them blocked. Returns prior
+ * active signal mask via pmask, to be restored by the main thread
+ * after pthread_create().
+ */
+#ifndef SYS_WINNT
+void
+block_thread_signals(
+ sigset_t * pmask
+ )
+{
+ sigset_t block;
+
+ sigemptyset(&block);
+# ifdef HAVE_SIGNALED_IO
+# ifdef SIGIO
+ sigaddset(&block, SIGIO);
+# endif /* SIGIO */
+# ifdef SIGIO
+ sigaddset(&block, SIGPOLL);
+# endif /* SIGIO */
+# endif /* HAVE_SIGNALED_IO */
+ sigaddset(&block, SIGALRM);
+ sigaddset(&block, MOREDEBUGSIG);
+ sigaddset(&block, LESSDEBUGSIG);
+# ifdef SIGDIE1
+ sigaddset(&block, SIGDIE1);
+# endif
+# ifdef SIGDIE2
+ sigaddset(&block, SIGDIE2);
+# endif
+# ifdef SIGDIE3
+ sigaddset(&block, SIGDIE3);
+# endif
+# ifdef SIGDIE4
+ sigaddset(&block, SIGDIE4);
+# endif
+# ifdef SIGBUS
+ sigaddset(&block, SIGBUS);
+# endif
+ sigemptyset(pmask);
+ pthread_sigmask(SIG_BLOCK, &block, pmask);
+}
+#endif /* !SYS_WINNT */
+
+
/*
* prepare_child_sems()
*
#if !defined(VMS)
# if !defined SYS_WINNT || defined(SYS_CYGWIN32)
# ifdef HAVE_TIMER_CREATE
- static timer_t timer_id;
- struct itimerspec itimer;
+static timer_t timer_id;
+typedef struct itimerspec intervaltimer;
+# define itv_frac tv_nsec
# else
- struct itimerval itimer;
+typedef struct itimerval intervaltimer;
+# define itv_frac tv_usec
# endif
+intervaltimer itimer;
# endif
#endif
+#if !defined(SYS_WINNT) && !defined(VMS)
+void set_timer_or_die(const intervaltimer *);
+#endif
+
+
+#if !defined(SYS_WINNT) && !defined(VMS)
+void
+set_timer_or_die(
+ const intervaltimer * ptimer
+ )
+{
+ const char * setfunc;
+ int rc;
+
+# ifdef HAVE_TIMER_CREATE
+ setfunc = "timer_settime";
+ rc = timer_settime(timer_id, 0, &itimer, NULL);
+# else
+ setfunc = "setitimer";
+ rc = setitimer(ITIMER_REAL, &itimer, NULL);
+# endif
+ if (-1 == rc) {
+ msyslog(LOG_ERR, "interval timer %s failed, %m\n",
+ setfunc);
+ exit(1);
+ }
+}
+#endif /* !SYS_WINNT && !VMS */
+
+
/*
* reinit_timer - reinitialize interval timer after a clock step.
*/
reinit_timer(void)
{
#if !defined(SYS_WINNT) && !defined(VMS)
-# ifdef HAVE_TIMER_CREATE
+ ZERO(itimer);
+# ifdef HAVE_TIMER_CREATE
timer_gettime(timer_id, &itimer);
- if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- }
- if (itimer.it_value.tv_nsec < 0 ) {
- itimer.it_value.tv_nsec = 0;
- }
- if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_nsec == 0) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_value.tv_nsec = 0;
- }
- itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_nsec = 0;
- timer_settime(timer_id, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
-# else
+# else
getitimer(ITIMER_REAL, &itimer);
- if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- }
- if (itimer.it_value.tv_usec < 0 ) {
- itimer.it_value.tv_usec = 0;
- }
- if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_usec == 0) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_value.tv_usec = 0;
- }
- itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_usec = 0;
- setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
-# endif
+# endif
+ if (itimer.it_value.tv_sec < 0 ||
+ itimer.it_value.tv_sec > (1 << EVENT_TIMEOUT))
+ itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
+ if (itimer.it_value.itv_frac < 0)
+ itimer.it_value.itv_frac = 0;
+ if (0 == itimer.it_value.tv_sec &&
+ 0 == itimer.it_value.itv_frac)
+ itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
+ itimer.it_interval.tv_sec = (1 << EVENT_TIMEOUT);
+ itimer.it_interval.itv_frac = 0;
+ set_timer_or_die(&itimer);
# endif /* VMS */
}
+
/*
* init_timer - initialize the timer data structures
*/
/*
* Initialize...
*/
- alarm_flag = 0;
+ alarm_flag = FALSE;
alarm_overflow = 0;
adjust_timer = 1;
stats_timer = HOUR;
*/
# ifndef VMS
# ifdef HAVE_TIMER_CREATE
- if (timer_create(CLOCK_REALTIME, NULL, &timer_id) == TC_ERR) {
- fprintf (stderr, "timer create FAILED\n");
- exit (0);
+ if (TC_ERR == timer_create(CLOCK_REALTIME, NULL, &timer_id)) {
+ msyslog(LOG_ERR, "timer_create failed, %m\n");
+ exit(1);
}
- signal_no_reset(SIGALRM, alarming);
- itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_nsec = itimer.it_value.tv_nsec = 0;
- timer_settime(timer_id, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
-# else
- (void) signal_no_reset(SIGALRM, alarming);
- itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_usec = itimer.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
# endif
+ signal_no_reset(SIGALRM, alarming);
+ itimer.it_interval.tv_sec =
+ itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
+ itimer.it_interval.itv_frac = itimer.it_value.itv_frac = 0;
+ set_timer_or_die(&itimer);
# else /* VMS follows */
vmsinc[0] = 10000000; /* 1 sec */
vmsinc[1] = 0;
exit(1);
}
else {
- DWORD Period = (1<<EVENT_TIMEOUT) * 1000;
- LARGE_INTEGER DueTime;
+ DWORD Period;
+ LARGE_INTEGER DueTime;
+ BOOL rc;
+
+ Period = (1 << EVENT_TIMEOUT) * 1000;
DueTime.QuadPart = Period * 10000i64;
- if (!SetWaitableTimer(WaitableTimerHandle, &DueTime, Period, NULL, NULL, FALSE) != NO_ERROR) {
+ rc = SetWaitableTimer(WaitableTimerHandle, &DueTime,
+ Period, NULL, NULL, FALSE);
+ if (!rc) {
msyslog(LOG_ERR, "SetWaitableTimer failed: %m");
exit(1);
}
void
timer(void)
{
- register struct peer *peer, *next_peer;
- l_fp now;
+ struct peer * p;
+ struct peer * next_peer;
+ l_fp now;
/*
* The basic timerevent is one second. This is used to adjust the
adjust_timer += 1;
adj_host_clock();
#ifdef REFCLOCK
- for (peer = peer_list; peer != NULL; peer = next_peer) {
- next_peer = peer->p_link;
- if (peer->flags & FLAG_REFCLOCK)
- refclock_timer(peer);
+ for (p = peer_list; p != NULL; p = next_peer) {
+ next_peer = p->p_link;
+ if (FLAG_REFCLOCK & p->flags)
+ refclock_timer(p);
}
#endif /* REFCLOCK */
}
* careful here, since the peer structure might go away as the
* result of the call.
*/
- for (peer = peer_list; peer != NULL; peer = next_peer) {
- next_peer = peer->p_link;
- if (peer->action != NULL && peer->nextaction <=
- current_time)
- (*peer->action)(peer);
+ for (p = peer_list; p != NULL; p = next_peer) {
+ next_peer = p->p_link;
+ if (p->action != NULL && p->nextaction <= current_time)
+ (*p->action)(p);
/*
* Restrain the non-burst packet rate not more
* usually tripped using iburst and minpoll of
* 128 s or less.
*/
- if (peer->throttle > 0)
- peer->throttle--;
- if (peer->nextdate <= current_time) {
+ if (p->throttle > 0)
+ p->throttle--;
+ if (p->nextdate <= current_time) {
#ifdef REFCLOCK
- if (peer->flags & FLAG_REFCLOCK)
- refclock_transmit(peer);
+ if (FLAG_REFCLOCK & p->flags)
+ refclock_transmit(p);
else
- transmit(peer);
-#else /* REFCLOCK */
- transmit(peer);
-#endif /* REFCLOCK */
+#endif /* REFCLOCK */
+ transmit(p);
}
}
int sig
)
{
-#if !defined(VMS)
- if (initializing)
- return;
- if (alarm_flag)
- alarm_overflow++;
- else
- alarm_flag++;
-#else /* VMS AST routine */
+#ifdef DEBUG
+ const char *msg = "alarming: initializing TRUE\n";
+#endif
+
if (!initializing) {
- if (alarm_flag) alarm_overflow++;
- else alarm_flag = 1; /* increment is no good */
+ if (alarm_flag) {
+ alarm_overflow++;
+#ifdef DEBUG
+ msg = "alarming: overflow\n";
+#endif
+ } else {
+# ifndef VMS
+ alarm_flag++;
+# else
+ /* VMS AST routine, increment is no good */
+ alarm_flag = 1;
+# endif
+#ifdef DEBUG
+ msg = "alarming: normal\n";
+#endif
+ }
}
- lib$addx(&vmsinc,&vmstimer,&vmstimer);
- sys$setimr(0,&vmstimer,alarming,alarming,0);
-#endif /* VMS */
+# ifdef VMS
+ lib$addx(&vmsinc, &vmstimer, &vmstimer);
+ sys$setimr(0, &vmstimer, alarming, alarming, 0);
+# endif
+#ifdef DEBUG
+ if (debug)
+ write(2, msg, strlen(msg));
+#endif
}
#endif /* SYS_WINNT */
+
void
timer_interfacetimeout(u_long timeout)
{
struct rlimit rl;
# endif
# endif
+
# ifdef HAVE_UMASK
uv = umask(0);
if (uv)
else
umask(022);
# endif
-
progname = argv[0];
initializing = TRUE; /* mark that we are initializing */
parse_cmdline_opts(&argc, &argv);
cap_free(caps);
}
# endif /* HAVE_LINUX_CAPABILITIES */
- root_dropped = 1;
+ root_dropped = TRUE;
fork_deferred_worker();
} /* if (droproot) */
# endif /* HAVE_DROPROOT */
* between checking for alarms and doing the select().
* Mostly harmless, I think.
*/
- /* On VMS, I suspect that select() can't be interrupted
+ /*
+ * On VMS, I suspect that select() can't be interrupted
* by a "signal" either, so I take the easy way out and
* have select() time out after one second.
* System clock updates really aren't time-critical,
# else /* normal I/O */
BLOCK_IO_AND_ALARM();
- was_alarmed = 0;
- for (;;)
- {
+ was_alarmed = FALSE;
+ for (;;) {
# ifndef HAVE_SIGNALED_IO
fd_set rdfdes;
int nfound;
# endif
- if (alarm_flag) /* alarmed? */
- {
- was_alarmed = 1;
- alarm_flag = 0;
+ if (alarm_flag) { /* alarmed? */
+ was_alarmed = TRUE;
+ alarm_flag = FALSE;
}
- if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
- {
+ if (!was_alarmed && !has_full_recv_buffer()) {
/*
* Nothing to do. Wait for something.
*/
# ifndef HAVE_SIGNALED_IO
rdfdes = activefds;
-# if defined(VMS) || defined(SYS_VXWORKS)
+# if !defined(VMS) && !defined(SYS_VXWORKS)
+ nfound = select(maxactivefd + 1, &rdfdes, NULL,
+ NULL, NULL);
+# else /* VMS, VxWorks */
/* make select() wake up after one second */
{
struct timeval t1;
- t1.tv_sec = 1; t1.tv_usec = 0;
- nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
- (fd_set *)0, &t1);
+ t1.tv_sec = 1;
+ t1.tv_usec = 0;
+ nfound = select(maxactivefd + 1,
+ &rdfdes, NULL, NULL,
+ &t1);
}
-# else
- nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
- (fd_set *)0, (struct timeval *)0);
-# endif /* VMS */
- if (nfound > 0)
- {
+# endif /* VMS, VxWorks */
+ if (nfound > 0) {
l_fp ts;
get_systime(&ts);
- (void)input_handler(&ts);
- }
- else if (nfound == -1 && errno != EINTR)
+ input_handler(&ts);
+ } else if (nfound == -1 && errno != EINTR) {
msyslog(LOG_ERR, "select() error: %m");
+ }
# ifdef DEBUG
- else if (debug > 5)
+ else if (debug > 4) {
msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
+ } else {
+ DPRINTF(1, ("select() returned %d: %m\n", nfound));
+ }
# endif /* DEBUG */
# else /* HAVE_SIGNALED_IO */
wait_for_signal();
# endif /* HAVE_SIGNALED_IO */
- if (alarm_flag) /* alarmed? */
- {
- was_alarmed = 1;
- alarm_flag = 0;
+ if (alarm_flag) { /* alarmed? */
+ was_alarmed = TRUE;
+ alarm_flag = FALSE;
}
}
- if (was_alarmed)
- {
+ if (was_alarmed) {
UNBLOCK_IO_AND_ALARM();
/*
* Out here, signals are unblocked. Call timer routine
* to process expiry.
*/
timer();
- was_alarmed = 0;
+ was_alarmed = FALSE;
BLOCK_IO_AND_ALARM();
}
tsa = pts;
# endif
rbuf = get_full_recv_buffer();
- while (rbuf != NULL)
- {
- if (alarm_flag)
- {
- was_alarmed = 1;
- alarm_flag = 0;
+ while (rbuf != NULL) {
+ if (alarm_flag) {
+ was_alarmed = TRUE;
+ alarm_flag = FALSE;
}
UNBLOCK_IO_AND_ALARM();
- if (was_alarmed)
- { /* avoid timer starvation during lengthy I/O handling */
+ if (was_alarmed) {
+ /* avoid timer starvation during lengthy I/O handling */
timer();
- was_alarmed = 0;
+ was_alarmed = FALSE;
}
/*
* Call the data procedure to handle each received
* packet.
*/
- if (rbuf->receiver != NULL) /* This should always be true */
- {
+ if (rbuf->receiver != NULL) {
# ifdef DEBUG_TIMING
l_fp dts = pts;
collect_timing(rbuf, "buffer processing delay", 1, &dts);
bufcount++;
# endif
- (rbuf->receiver)(rbuf);
+ (*rbuf->receiver)(rbuf);
} else {
- msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
+ msyslog(LOG_ERR, "fatal: receive buffer callback NULL");
abort();
}