93 lines
2.8 KiB
Diff
93 lines
2.8 KiB
Diff
|
From 993bd6ab583c077eb0e94fb25f090eb164922435 Mon Sep 17 00:00:00 2001
|
||
|
From: Lubomir Rintel <lkundrak@v3.sk>
|
||
|
Date: Wed, 6 May 2015 11:52:27 +0200
|
||
|
Subject: [PATCH 1/4] dns: kill plugin child synchronously to avoid restart
|
||
|
race (rh #1161232) (bgo #728342)
|
||
|
|
||
|
NM was killing the dnsmasq local caching nameserver process and immediately
|
||
|
starting a new one, and new process couldn't bind to 127.0.0.1 because the
|
||
|
old one hadn't quit yet. Thus the new process quit, and the user was
|
||
|
left with no split DNS at all.
|
||
|
|
||
|
While this does introduce more synchronous waiting into the connection
|
||
|
process, it's not that much time and NM will kill dnsmasq if it hasn't
|
||
|
quit after 1 second. The longer-term fix is to use dnsmasq's D-Bus
|
||
|
interface to update DNS without respawning it.
|
||
|
|
||
|
https://bugzilla.gnome.org/show_bug.cgi?id=728342
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1161232
|
||
|
|
||
|
This is a rework of 10aff12526a2fc4b2d099df2710fdb040ccd9e4c. The newer
|
||
|
branches have ff3b753 (core: use nm_utils_kill_child_async() and
|
||
|
nm_utils_kill_child_sync()) which in turn relies on 1f84185 (core: add
|
||
|
nm_utils_kill_child_async() and nm_utils_kill_child_sync() function) that is
|
||
|
not entirely trivial to backport.
|
||
|
---
|
||
|
src/dns-manager/nm-dns-plugin.c | 41 ++++++++++++-----------------------------
|
||
|
1 file changed, 12 insertions(+), 29 deletions(-)
|
||
|
|
||
|
diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c
|
||
|
index e85b2a0..549efe3 100644
|
||
|
--- a/src/dns-manager/nm-dns-plugin.c
|
||
|
+++ b/src/dns-manager/nm-dns-plugin.c
|
||
|
@@ -196,29 +196,6 @@ nm_dns_plugin_child_spawn (NMDnsPlugin *self,
|
||
|
return priv->pid;
|
||
|
}
|
||
|
|
||
|
-typedef struct {
|
||
|
- int pid;
|
||
|
- char *progname;
|
||
|
-} KillInfo;
|
||
|
-
|
||
|
-static gboolean
|
||
|
-ensure_killed (gpointer data)
|
||
|
-{
|
||
|
- KillInfo *info = data;
|
||
|
-
|
||
|
- if (kill (info->pid, 0) == 0)
|
||
|
- kill (info->pid, SIGKILL);
|
||
|
-
|
||
|
- /* ensure the child is reaped */
|
||
|
- nm_log_dbg (LOGD_DNS, "waiting for %s pid %d to exit", info->progname, info->pid);
|
||
|
- waitpid (info->pid, NULL, 0);
|
||
|
- nm_log_dbg (LOGD_DNS, "dnsmasq pid %d cleaned up", info->pid);
|
||
|
-
|
||
|
- g_free (info->progname);
|
||
|
- g_free (info);
|
||
|
- return FALSE;
|
||
|
-}
|
||
|
-
|
||
|
gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self)
|
||
|
{
|
||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||
|
@@ -229,14 +206,20 @@ gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self)
|
||
|
}
|
||
|
|
||
|
if (priv->pid) {
|
||
|
- KillInfo *info;
|
||
|
|
||
|
if (kill (priv->pid, SIGTERM) == 0) {
|
||
|
- info = g_malloc0 (sizeof (KillInfo));
|
||
|
- info->pid = priv->pid;
|
||
|
- info->progname = g_strdup (priv->progname);
|
||
|
- g_timeout_add_seconds (2, ensure_killed, info);
|
||
|
- } else {
|
||
|
+ int counter = 20;
|
||
|
+
|
||
|
+ /* Wait up to 2 seconds synchronously. */
|
||
|
+ while (counter--) {
|
||
|
+ if (waitpid (priv->pid, NULL, WNOHANG))
|
||
|
+ break;
|
||
|
+ g_usleep (100000);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (kill (priv->pid, 0) == 0) {
|
||
|
+ /* Not dead yet. */
|
||
|
kill (priv->pid, SIGKILL);
|
||
|
|
||
|
/* ensure the child is reaped */
|
||
|
--
|
||
|
2.4.0
|
||
|
|