File kdump-netcheck-0002-netlink-timeout.patch of Package kdump

Date: Fri Oct 9 22:13:00 2015 +0200
From: Petr Tesarik <ptesarik@suse.com>
Subject: Add timeout handling to NetLink receive
References: bsc#944201
Patch-mainline: v0.8.16
Git-commit 46e888eebbb409de890e9406e8c0e792848b26f4

The monitoring socket must have a way to time out if no change happens
for some time, otherwise it may hang infinitely waiting for Godot^W
a change that never happens. This is best implemented with a poll()
call inside the receive() method.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>

---
 kdumptool/routable.cc |   42 ++++++++++++++++++++++++++++++++++++++++--
 kdumptool/routable.h  |    2 +-
 2 files changed, 41 insertions(+), 3 deletions(-)

--- a/kdumptool/routable.cc
+++ b/kdumptool/routable.cc
@@ -28,6 +28,8 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <errno.h>
+#include <poll.h>
+#include <time.h>
 
 #include "global.h"
 #include "routable.h"
@@ -44,6 +46,14 @@ class NetLink {
 
 	~NetLink();
 
+	void setTimeout(int timeout)
+	throw ()
+	{ m_timeout = timeout; }
+
+	int getTimeout(void) const
+	throw ()
+	{ return m_timeout; }
+
 	int checkRoute(const struct addrinfo *ai);
 
 	int waitRouteChange(void);
@@ -80,6 +90,8 @@ class NetLink {
 	{ return m_message; }
 
     private:
+	int m_timeout;
+
 	int m_fd;
 	struct sockaddr_nl m_local;
 	static unsigned m_seq;
@@ -93,7 +105,7 @@ unsigned NetLink::m_seq;
 
 // -----------------------------------------------------------------------------
 NetLink::NetLink(unsigned subscribe, size_t recv_max)
-    : m_buflen(recv_max)
+    : m_timeout(-1), m_buflen(recv_max)
 {
     struct sockaddr_nl sa;
     socklen_t salen;
@@ -162,6 +174,8 @@ int NetLink::receive(const RecvCheck &rc
     struct sockaddr_nl nladdr;
     struct iovec iov;
     struct msghdr msg;
+    struct pollfd pd;
+    struct timespec tsnow, tsend;
 
     m_message = NULL;
 
@@ -170,9 +184,32 @@ int NetLink::receive(const RecvCheck &rc
     msg.msg_iov = &iov;
     msg.msg_iovlen = 1;
 
+    pd.fd = m_fd;
+    pd.events = POLLIN;
+
+    clock_gettime(CLOCK_MONOTONIC, &tsend);
+    tsend.tv_sec += m_timeout;
+
     while (1) {
 	struct nlmsghdr *nh;
 	ssize_t len;
+	int timeout;
+	int res;
+
+	if (m_timeout >= 0) {
+	    clock_gettime(CLOCK_MONOTONIC, &tsnow);
+	    timeout = (tsend.tv_sec - tsnow.tv_sec) * 1000;
+	    timeout += (tsend.tv_nsec - tsnow.tv_nsec) / 1000000L;
+	    if (timeout < 0)
+		return -ETIME;
+	} else
+	    timeout = -1;
+
+	res = poll(&pd, 1, timeout);
+	if (res < 0)
+	    throw KSystemError("Cannot poll netlink", errno);
+	if (!res)
+	    return -ETIME;
 
 	iov.iov_base = m_buffer;
 	iov.iov_len = m_buflen;
@@ -390,9 +427,10 @@ bool Routable::resolve(void)
 }
 
 // -----------------------------------------------------------------------------
-bool Routable::check(void)
+bool Routable::check(int timeout)
 {
     NetLink nl(RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE);
+    nl.setTimeout(timeout);
 
     while (!resolve())
 	if (nl.waitRouteChange() != 0)
--- a/kdumptool/routable.h
+++ b/kdumptool/routable.h
@@ -40,7 +40,7 @@ class Routable {
 
 	~Routable();
 
-	bool check(void);
+	bool check(int timeout);
 
     protected:
 	bool resolve(void)
openSUSE Build Service is sponsored by