Instead of copying a prepared fd_set to the fd_set used by select(),
fill it from scratch according to the array of file handlers before each
select() call. This should make the code simpler and save some memory
when other events are supported.
Replace SCH_*InputFileHandler() functions with more general
SCH_*FileHandler(), where events are specified as a new parameter and
which will later support other file events, e.g. file ready for ouput
and exception.
The file handlers have two new parameters: file descriptor and event.
Don't require the scheduler to be initialized in SCH_QuitProgram().
This fixes a crash when a signal is received between scheduler
finalization and chronyd exit.
Use UTI_GetRandomBytes() instead of random() to calculate the random
part of the timeout. This was the only remaining use of random() in the
code and the srandom() call can be removed.
To avoid problems in the very unlikely case where a timeout is so long
and new IDs are allocated so frequently that they would have a chance
to overflow and catch up with it, make sure before returning new ID that
it's currently not in use.
Timeout ID of zero can be now safely used to indicate that the timer is
not running. Remove the extra timer_running variables that were
necessary to track that.
Abort when the system time gets so close to the end of 32-bit time_t
that timeouts added by delay start to overflow. This is an addition to
the loop detector in dispatch_timeouts().
To detect forward time jumps, use a timestamp made before calling
select() instead of the first timeout in the queue. Also, if the timeout
value is modified by select() (e.g. on Linux) use it to get a more
accurate estimate of the elapsed time.
With cmdport 0 and port 0, it's now possible that there is no descriptor
watched or timer running, i.e. chronyd doing nothing and only waiting to
be terminated. Replace the assertion with LOG_FATAL to exit properly.
With special reference update modes, the timeout handlers may add or
remove file descriptors from the read fd set, so it needs to be copied
for select() call after they are dispatched. Also, they can now request
quit, so the exit flag needs to be checked before select() to avoid
hanging.
It could be triggered by delayed name resolving as it adds multiple new
timeouts which can be called in the same dispatching if the DNS responses
are slower than initial delay and sampling separation.
Compare number of dispatched events also with current number of
timeouts.
If more timeouts were handled than there were in the timer queue on
start, assume some code is scheduling timeouts with negative delays and
abort. Make the actual limit higher in case the machine is temporarily
overloaded and dispatching the handlers takes more time than was delay
of a scheduled timeout.
None of the current handlers really need it and with temperature
compensation enabled it would be necessary to undo the compensation
before passing it to the handlers.