chrony: Ignore late responses
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 6fb369a..913aab9 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)