gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self) { NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); if (priv->watch_id) { g_source_remove (priv->watch_id); priv->watch_id = 0; } if (priv->pid) { nm_utils_kill_child_sync (priv->pid, SIGTERM, LOGD_DNS, priv->progname, NULL, 1000, 0); priv->pid = 0; g_free (priv->progname); priv->progname = NULL; } if (priv->pidfile) { unlink (priv->pidfile); g_free (priv->pidfile); priv->pidfile = NULL; } return TRUE; }
static void finalize (GObject *object) { NMDnsPlugin *self = NM_DNS_PLUGIN (object); NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); g_free (priv->progname); g_free (priv->pidfile); G_OBJECT_CLASS (nm_dns_plugin_parent_class)->finalize (object); }
static void watch_cb (GPid pid, gint status, gpointer user_data) { NMDnsPlugin *self = NM_DNS_PLUGIN (user_data); NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); priv->pid = 0; g_free (priv->progname); priv->progname = NULL; g_signal_emit (self, signals[CHILD_QUIT], 0, status); }
static void dispose (GObject *object) { NMDnsPlugin *self = NM_DNS_PLUGIN (object); NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); if (!priv->disposed) { priv->disposed = TRUE; nm_dns_plugin_child_kill (self); } G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (object); }
GPid nm_dns_plugin_child_spawn (NMDnsPlugin *self, const char **argv, const char *pidfile, const char *kill_match) { NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); GError *error = NULL; char *cmdline; g_return_val_if_fail (argv != NULL, 0); g_return_val_if_fail (argv[0] != NULL, 0); g_warn_if_fail (priv->progname == NULL); g_free (priv->progname); priv->progname = g_path_get_basename (argv[0]); if (pidfile) { g_return_val_if_fail (kill_match != NULL, 0); kill_existing (priv->progname, pidfile, kill_match); g_free (priv->pidfile); priv->pidfile = g_strdup (pidfile); } nm_log_info (LOGD_DNS, "DNS: starting %s...", priv->progname); cmdline = g_strjoinv (" ", (char **) argv); nm_log_dbg (LOGD_DNS, "DNS: command line: %s", cmdline); g_free (cmdline); priv->pid = 0; if (g_spawn_async (NULL, (char **) argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, child_setup, NULL, &priv->pid, &error)) { nm_log_dbg (LOGD_DNS, "%s started with pid %d", priv->progname, priv->pid); priv->watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) watch_cb, self); } else { nm_log_warn (LOGD_DNS, "Failed to spawn %s: (%d) %s", priv->progname, error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); } return priv->pid; }
gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self) { NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); if (priv->watch_id) { g_source_remove (priv->watch_id); priv->watch_id = 0; } 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 { kill (priv->pid, SIGKILL); /* ensure the child is reaped */ nm_log_dbg (LOGD_DNS, "waiting for %s pid %d to exit", priv->progname, priv->pid); waitpid (priv->pid, NULL, 0); nm_log_dbg (LOGD_DNS, "%s pid %d cleaned up", priv->progname, priv->pid); } priv->pid = 0; g_free (priv->progname); priv->progname = NULL; } if (priv->pidfile) { unlink (priv->pidfile); g_free (priv->pidfile); priv->pidfile = NULL; } return TRUE; }