From 3bcf541f6ac8a467e5b0a2e7ab910d67115018ef Mon Sep 17 00:00:00 2001
From: Marek Vavrusa <marek.vavrusa@nic.cz>
Date: Thu, 16 Aug 2012 14:55:24 +0200
Subject: [PATCH] XFR handler is terminated by the interrupt request.

This allows to clear any existing requests in the queue,
preventing potential memory leaks on shutdown.

refs #1976
---
 src/common/evqueue.c          |  7 +++++--
 src/knot/server/server.c      |  7 ++-----
 src/knot/server/xfr-handler.c | 14 ++++++++++++--
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/common/evqueue.c b/src/common/evqueue.c
index 76141115f3..240ced618e 100644
--- a/src/common/evqueue.c
+++ b/src/common/evqueue.c
@@ -126,8 +126,11 @@ void evqueue_free(evqueue_t **q)
 	*q = 0;
 
 	/* Deinitialize. */
-	close(eq->fds[EVQUEUE_READFD]);
-	close(eq->fds[EVQUEUE_WRITEFD]);
+	for (int i = 0; i < 2; ++i) {
+		if (eq->fds[i] > -1) {
+			close(eq->fds[i]);
+		}
+	}
 	free(eq);
 }
 
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 4d01801cd5..06f89b5a99 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -651,16 +651,13 @@ void server_stop(server_t *server)
 {
 	dbg_server("server: stopping server\n");
 	
-	/* Wait for XFR master. */
-	xfr_stop(server->xfr_h);
+	/* Send termination event. */
+	evsched_schedule_term(server->sched, 0);
 
 	/* Interrupt XFR handler execution. */
 	if (server->xfr_h->interrupt) {
 		server->xfr_h->interrupt(server->xfr_h);
 	}
-	
-	/* Send termination event. */
-	evsched_schedule_term(server->sched, 0);
 
 	/* Lock RCU. */
 	rcu_read_lock();
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index 9b8055ad22..6662443f30 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -51,7 +51,13 @@
 void xfr_interrupt(xfrhandler_t *h)
 {
 	for(unsigned i = 0; i < h->unit->size; ++i) {
-		evqueue_write(h->workers[i]->q, "", 1);
+		evqueue_t *q = h->workers[i]->q;
+		if (evqueue_write(q, "", 1) == 1) {
+			close(q->fds[EVQUEUE_WRITEFD]);
+			q->fds[EVQUEUE_WRITEFD] = -1;
+		} else {
+			dt_stop_id(h->unit->threads[i]);
+		}
 	}
 }
 
@@ -1558,7 +1564,6 @@ int xfr_worker(dthread_t *thread)
 		fdset_begin(w->fdset, &it);
 		int rfd_event = 0;
 		while(nfds > 0) {
-			
 			/* Check if it request. */
 			if (it.fd == rfd) {
 				rfd_event = 1; /* Delay new tasks after processing. */
@@ -1605,6 +1610,11 @@ int xfr_worker(dthread_t *thread)
 				next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
 			}
 		}
+		
+		/* Check for interrupt request. */
+		if (ret == KNOTD_ENOTRUNNING) {
+			break;
+		}
 	}
 
 	/* Stop whole unit. */
-- 
GitLab