From: Miroslav Lichvar Date: Mon, 13 Jul 2026 14:38:00 +0000 (+0200) Subject: refclock: add option to ignore driver initialization errors X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fchrony.git refclock: add option to ignore driver initialization errors Add "optional" option to the refclock directive to skip the refclock if it cannot be initialized due to a missing device or feature, etc. --- diff --git a/conf.c b/conf.c index 01528c47..7164c9f6 100644 --- a/conf.c +++ b/conf.c @@ -969,12 +969,13 @@ static void parse_refclock(char *line) { int n, poll, dpoll, filter_length, pps_rate, min_samples_, max_samples_, sel_options; - int local, max_lock_age, max_unreach, pps_forced, sel_option, stratum, tai; + int local, max_lock_age, max_unreach, pps_forced, sel_option, stratum, tai, optional; uint32_t ref_id, lock_ref_id; double offset, delay, precision, max_dispersion, pulse_width; char *p, *cmd, *name, *param; RefclockParameters *refclock; + optional = 0; poll = 4; dpoll = 0; filter_length = 64; @@ -1054,6 +1055,9 @@ parse_refclock(char *line) } else if (!strcasecmp(cmd, "offset")) { if (sscanf(line, "%lf%n", &offset, &n) != 1) break; + } else if (!strcasecmp(cmd, "optional")) { + n = 0; + optional = 1; } else if (!strcasecmp(cmd, "delay")) { if (sscanf(line, "%lf%n", &delay, &n) != 1) break; @@ -1094,6 +1098,7 @@ parse_refclock(char *line) refclock->driver_parameter = param; refclock->driver_poll = dpoll; refclock->poll = poll; + refclock->optional = optional; refclock->filter_length = filter_length; refclock->local = local; refclock->pps_forced = pps_forced; diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index 414c9c51..3d2efb43 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -751,6 +751,10 @@ selected for synchronisation when it is unreachable (i.e. no valid sample was received in the last 8 polls). Only sources with at least one sample more recent than the oldest sample of all reachable sources can be selected. The default is 100000. +*optional*::: +This option indicates that the refclock device might be missing and *chronyd* +is allowed to start even if the driver fails to initialise, causing the source +to be ignored as if it was not specified in the configuration file. [[manual]]*manual*:: The *manual* directive enables support at run-time for the diff --git a/refclock.c b/refclock.c index d73e3c01..3816d124 100644 --- a/refclock.c +++ b/refclock.c @@ -151,7 +151,6 @@ RCL_AddRefclock(RefclockParameters *params) RCL_Instance inst; inst = MallocNew(struct RCL_Instance_Record); - *(RCL_Instance *)ARR_GetNewElement(refclocks) = inst; if (strcmp(params->driver_name, "SHM") == 0) { inst->driver = &RCL_SHM_driver; @@ -213,7 +212,7 @@ RCL_AddRefclock(RefclockParameters *params) inst->ref_id = params->ref_id; else { unsigned char ref[5] = { 0, 0, 0, 0, 0 }; - unsigned int index = ARR_GetSize(refclocks) - 1; + unsigned int index = ARR_GetSize(refclocks); snprintf((char *)ref, sizeof (ref), "%3.3s", params->driver_name); ref[3] = index % 10 + '0'; @@ -235,8 +234,13 @@ RCL_AddRefclock(RefclockParameters *params) inst->driver_poll = inst->poll; } - if (inst->driver->init && !inst->driver->init(inst)) - LOG_FATAL("refclock %s initialisation failed", params->driver_name); + if (inst->driver->init && !inst->driver->init(inst)) { + LOG(params->optional ? LOGS_ERR : LOGS_FATAL, "Could not initialise refclock %s %s", + params->driver_name, params->driver_parameter); + Free(inst->driver_parameter); + Free(inst); + return 0; + } /* Don't require more than one sample per poll and combine 60% of the samples closest to the median offset */ @@ -250,6 +254,8 @@ RCL_AddRefclock(RefclockParameters *params) params->driver_name, UTI_RefidToString(inst->ref_id), inst->poll, inst->driver_poll, params->filter_length); + *(RCL_Instance *)ARR_GetNewElement(refclocks) = inst; + return 1; } diff --git a/refclock.h b/refclock.h index 37d1ef38..a2228e99 100644 --- a/refclock.h +++ b/refclock.h @@ -36,6 +36,7 @@ typedef struct { char *driver_parameter; int driver_poll; int poll; + int optional; int filter_length; int local; int pps_forced; diff --git a/test/simulation/106-refclock b/test/simulation/106-refclock index dcbe3812..4eca0206 100755 --- a/test/simulation/106-refclock +++ b/test/simulation/106-refclock @@ -207,4 +207,29 @@ check_file_messages "20.* PHC0 .* - ? " 2499 2501 refclocks.log || test_fail check_file_messages "20.* PHC0 " 0 0 tracking.log || test_fail rm -f tmp/refclocks.log tmp/tracking.log +reset_test_options + +cmdmon_unix=0 +client_conf=" +refclock PHC tmp/nosuch/ptp0 optional +refclock SOCK tmp/nosuch/sock optional +" +num_refclocks=2 +if check_config_h 'FEAT_PPS 1'; then + client_conf+="refclock PPS tmp/nosuch/pps optional + " + num_refclocks=$[num_refclocks + 1] +fi +if check_config_h 'FEAT_RTC 1'; then + client_conf+="refclock RTC tmp/nosuch/rtc optional + " + num_refclocks=$[num_refclocks + 1] +fi + +run_test || test_fail +check_chronyd_exit || test_fail +check_sync || test_fail +check_log_messages "Could not initialise refclock \(PHC\|PPS\|RTC\|SOCK\)" \ + $num_refclocks $num_refclocks || test_fail + test_pass