fix chronyc getting stuck in infinite loop after clock step
This commit is contained in:
parent
f15bb7e2fc
commit
6bdb94e9b0
94
chrony-select-timeout.patch
Normal file
94
chrony-select-timeout.patch
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
commit d0b24860363a3704e28569ce9a6987717834edea
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Dec 5 11:08:24 2017 +0100
|
||||||
|
|
||||||
|
client: don't call select() with invalid timeout
|
||||||
|
|
||||||
|
If the system clock was stepped forward after chronyc sent a request and
|
||||||
|
before it read the clock in order to calculate the receive timeout,
|
||||||
|
select() could be called with a negative timeout, which resulted in an
|
||||||
|
infinite loop waiting for select() to succeed.
|
||||||
|
|
||||||
|
Fix the submit_request() function to not call select() with a negative
|
||||||
|
timeout. Also, return immediately on any error of select().
|
||||||
|
|
||||||
|
diff --git a/client.c b/client.c
|
||||||
|
index 5c3a99e..4e23158 100644
|
||||||
|
--- a/client.c
|
||||||
|
+++ b/client.c
|
||||||
|
@@ -1394,9 +1394,16 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
|
|
||||||
|
timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
|
||||||
|
UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
|
||||||
|
- UTI_DoubleToTimeval(timeout, &tv);
|
||||||
|
DEBUG_LOG("Timeout %f seconds", timeout);
|
||||||
|
|
||||||
|
+ /* Avoid calling select() with an invalid timeout */
|
||||||
|
+ if (timeout <= 0.0) {
|
||||||
|
+ new_attempt = 1;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ UTI_DoubleToTimeval(timeout, &tv);
|
||||||
|
+
|
||||||
|
FD_ZERO(&rdfd);
|
||||||
|
FD_ZERO(&wrfd);
|
||||||
|
FD_ZERO(&exfd);
|
||||||
|
@@ -1410,6 +1417,7 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
|
|
||||||
|
if (select_status < 0) {
|
||||||
|
DEBUG_LOG("select failed : %s", strerror(errno));
|
||||||
|
+ return 0;
|
||||||
|
} else if (select_status == 0) {
|
||||||
|
/* Timeout must have elapsed, try a resend? */
|
||||||
|
new_attempt = 1;
|
||||||
|
|
||||||
|
commit 6863e43269fe27ce2744eb643295f31c00ec176d
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Dec 12 11:03:04 2017 +0100
|
||||||
|
|
||||||
|
client: avoid reading clock after sending request
|
||||||
|
|
||||||
|
If chronyc sent a request which caused chronyd to step the clock (e.g.
|
||||||
|
makestep, settime) and the second reading of the clock before calling
|
||||||
|
select() to wait for a response happened after the clock was stepped, a
|
||||||
|
new request could be sent immediately and chronyd would process the same
|
||||||
|
command twice. If the second request failed (e.g. a settime request too
|
||||||
|
close to the first request), chronyc would report an error.
|
||||||
|
|
||||||
|
Change the submit_request() function to read the clock only once per
|
||||||
|
select() to wait for the first response even when the clock was stepped.
|
||||||
|
|
||||||
|
diff --git a/client.c b/client.c
|
||||||
|
index a04dcb8..7d1e346 100644
|
||||||
|
--- a/client.c
|
||||||
|
+++ b/client.c
|
||||||
|
@@ -1347,15 +1347,15 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
|
new_attempt = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
+ if (gettimeofday(&tv, NULL))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
if (new_attempt) {
|
||||||
|
new_attempt = 0;
|
||||||
|
|
||||||
|
if (n_attempts > max_retries)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- if (gettimeofday(&tv, NULL))
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
UTI_TimevalToTimespec(&tv, &ts_start);
|
||||||
|
|
||||||
|
UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
|
||||||
|
@@ -1383,9 +1383,6 @@ submit_request(CMD_Request *request, CMD_Reply *reply)
|
||||||
|
DEBUG_LOG("Sent %d bytes", command_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (gettimeofday(&tv, NULL))
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
UTI_TimevalToTimespec(&tv, &ts_now);
|
||||||
|
|
||||||
|
/* Check if the clock wasn't stepped back */
|
@ -21,6 +21,8 @@ Source10: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/c
|
|||||||
|
|
||||||
# add NTP servers from DHCP when starting service
|
# add NTP servers from DHCP when starting service
|
||||||
Patch1: chrony-service-helper.patch
|
Patch1: chrony-service-helper.patch
|
||||||
|
# fix chronyc getting stuck in infinite loop after clock step
|
||||||
|
Patch2: chrony-select-timeout.patch
|
||||||
|
|
||||||
BuildRequires: libcap-devel libedit-devel nss-devel pps-tools-devel
|
BuildRequires: libcap-devel libedit-devel nss-devel pps-tools-devel
|
||||||
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
|
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
|
||||||
@ -54,6 +56,7 @@ clocks, system real-time clock or manual input as time references.
|
|||||||
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
|
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
|
||||||
%{?gitpatch:%patch0 -p1}
|
%{?gitpatch:%patch0 -p1}
|
||||||
%patch1 -p1 -b .service-helper
|
%patch1 -p1 -b .service-helper
|
||||||
|
%patch2 -p1 -b .select-timeout
|
||||||
|
|
||||||
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
|
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user