]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
chrony: Ignore late responses 2896/head
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 15 Aug 2018 10:21:36 +0000 (12:21 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 24 Aug 2018 07:34:59 +0000 (09:34 +0200)
If a response from chronyd was not received before the timeout (e.g. on a
busy system), it would wait in the receive queue and be processed as a
response of the next request. It would fail the sequence check and cause
the plugin to return with an error. The latest response would wait in
the receive queue and this would repeat forever.

Flush the receive queue before sending a new batch of requests to
prevent this situation from happening.

src/chrony.c

index 6fb369a2f167b043618318b98c88764902fd5540..913aab94dd60e4c3c989151f6b526aac0ad8ac07 100644 (file)
 #include <arpa/inet.h> /* ntohs/ntohl */
 #endif
 
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
 #define CONFIG_KEY_HOST "Host"
 #define CONFIG_KEY_PORT "Port"
 #define CONFIG_KEY_TIMEOUT "Timeout"
@@ -440,6 +445,15 @@ static int chrony_recv_response(tChrony_Response *p_resp,
   }
 }
 
+static void chrony_flush_recv_queue(void) {
+  char buf[1];
+
+  if (g_chrony_is_connected) {
+    while (recv(g_chrony_socket, buf, sizeof(buf), MSG_DONTWAIT) > 0)
+      ;
+  }
+}
+
 static int chrony_query(const int p_command, tChrony_Request *p_req,
                         tChrony_Response *p_resp, size_t *p_resp_size) {
   /* Check connection. We simply perform one try as collectd already handles
@@ -964,6 +978,9 @@ static int chrony_read(void) {
     g_chrony_seq_is_initialized = 1;
   }
 
+  /* Ignore late responses that may have been received */
+  chrony_flush_recv_queue();
+
   /* Get daemon stats */
   rc = chrony_request_daemon_stats();
   if (rc != CHRONY_RC_OK)