[evolution] Implement a new 'killev' program.



commit c6727d66ade72df6fbaff9f111a06993aeefdecc
Author: Matthew Barnes <mbarnes redhat com>
Date:   Thu Nov 26 21:16:40 2009 -0500

    Implement a new 'killev' program.
    
    For now this only terminates Evolution, but the same basic approach
    should also be used with the Evolution-Data-Server D-Bus services.

 shell/Makefile.am |   18 ++++++-
 shell/killev.c    |  158 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 shell/main.c      |   22 +------
 3 files changed, 178 insertions(+), 20 deletions(-)
---
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 541f941..6ff40ba 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -114,12 +114,12 @@ evolution_CPPFLAGS =						\
 	-DEVOLUTION_ICONDIR=\""$(icondir)"\"			\
 	-DEVOLUTION_MODULEDIR=\""$(moduledir)"\"		\
 	-DEVOLUTION_RULEDIR=\""$(privdatadir)"\"		\
+	-DEVOLUTION_TOOLSDIR=\""$(privlibexecdir)"\"		\
 	-DEVOLUTION_UIDIR=\""$(uidir)"\"			\
 	-DPREFIX=\""$(prefix)"\"				\
 	-DSYSCONFDIR=\""$(sysconfdir)"\"			\
 	-DDATADIR=\""$(datadir)"\"				\
 	-DLIBDIR=\""$(datadir)"\"				\
-	-DG_LOG_DOMAIN=\"evolution-shell\"			\
 	$(TZDIALOG_CFLAGS)					\
 	$(SHELL_CFLAGS)
 
@@ -142,6 +142,22 @@ if OS_WIN32
 evolution_LDFLAGS = -mwindows
 endif
 
+# Killev utility
+
+if OS_WIN32
+else
+privlibexec_PROGRAMS = killev
+endif
+
+killev_CPPFLAGS =						\
+	$(AM_CPPFLAGS)						\
+	-DEVOLUTION_LOCALEDIR=\""$(localedir)"\"		\
+	$(GNOME_PLATFORM_CFLAGS)
+
+killev_SOURCES = killev.c
+
+killev_LDADD = $(GNOME_PLATFORM_LIBS)
+
 # Misc stuff
 
 error_DATA = shell.error
diff --git a/shell/killev.c b/shell/killev.c
new file mode 100644
index 0000000..d1eb523
--- /dev/null
+++ b/shell/killev.c
@@ -0,0 +1,158 @@
+/*
+ * killev.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+/* Seconds to wait after asking Evolution to terminate gracefully.
+ * If the process has not terminated before the timeout expires,
+ * then we get violent. */
+#define EVOLUTION_SHUTDOWN_TIMEOUT 5
+
+static GPid evolution_pid;
+static GMainLoop *main_loop;
+
+static void
+file_monitor_changed_cb (GFileMonitor *monitor,
+                         GFile *file,
+                         GFile *not_used,
+                         GFileMonitorEvent event_type)
+{
+	if (event_type != G_FILE_MONITOR_EVENT_DELETED)
+		return;
+
+	g_print ("Evolution process exited normally\n");
+
+	g_main_loop_quit (main_loop);
+}
+
+static gboolean
+evolution_not_responding_cb (void)
+{
+	g_print ("No response from Evolution -- killing the process\n");
+
+	/* Kill the process. */
+	kill ((pid_t) evolution_pid, SIGTERM);
+
+	g_main_loop_quit (main_loop);
+
+	return FALSE;
+}
+
+static gboolean
+get_evolution_pid (GFile *file)
+{
+	gint64 v_int64;
+	gchar *contents = NULL;
+	gboolean success = FALSE;
+
+	/* Try to read Evolution's PID from its .running file. */
+
+	if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
+		goto exit;
+
+	/* Try to extract an integer value from the string. */
+	v_int64 = g_ascii_strtoll (contents, NULL, 10);
+	if (!(v_int64 > 0 && v_int64 < G_MAXINT64))
+		goto exit;
+
+	/* XXX Probably not portable. */
+	evolution_pid = (GPid) v_int64;
+
+	success = TRUE;
+
+exit:
+	g_free (contents);
+
+	return success;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+	GFile *pid_file;
+	GFileMonitor *monitor;
+	gchar *filename;
+	GError *error = NULL;
+
+	bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	g_type_init ();
+
+	/* XXX If e_get_user_data_dir() ever gets moved to libedataserver,
+	 *     use that instead of hard-coding the directory path here. */
+	filename = g_build_filename (
+		g_get_home_dir (), ".evolution", ".running", NULL);
+	pid_file = g_file_new_for_path (filename);
+	g_free (filename);
+
+	if (!get_evolution_pid (pid_file)) {
+		g_printerr ("Could not find Evolution's process ID\n");
+		exit (EXIT_FAILURE);
+	}
+
+	/* Play it safe here and bail if something goes wrong.  We don't
+	 * want to just skip to the killing if we can't ask Evolution to
+	 * terminate gracefully.  Despite our name we actually want to
+	 * -avoid- killing Evolution if at all possible. */
+	if (!g_spawn_command_line_async ("evolution --quit", &error)) {
+		g_printerr ("%s", error->message);
+		g_error_free (error);
+		exit (EXIT_FAILURE);
+	}
+
+	/* Now we set up a monitor on Evolution's .running file.
+	 * If Evolution is still responsive it will delete this
+	 * file just before terminating and we'll be notified. */
+	monitor = g_file_monitor_file (pid_file, 0, NULL, &error);
+	if (error != NULL) {
+		g_printerr ("%s", error->message);
+		g_error_free (error);
+		exit (EXIT_FAILURE);
+	}
+
+	g_signal_connect (
+		monitor, "changed",
+		G_CALLBACK (file_monitor_changed_cb), NULL);
+
+	g_timeout_add_seconds (
+		EVOLUTION_SHUTDOWN_TIMEOUT, (GSourceFunc)
+		evolution_not_responding_cb, NULL);
+
+	/* Start the clock. */
+
+	main_loop = g_main_loop_new (NULL, TRUE);
+	g_main_loop_run (main_loop);
+	g_main_loop_unref (main_loop);
+
+	g_object_unref (monitor);
+
+	return EXIT_SUCCESS;
+}
diff --git a/shell/main.c b/shell/main.c
index 396cd69..c37ccc4 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -390,26 +390,10 @@ set_paths (void)
 static void G_GNUC_NORETURN
 shell_force_shutdown (void)
 {
-	gchar *program;
+	gchar *filename;
 
-	/* This is not as destructive as it was in the Bonobo era.
-	 * The Evolution-Data-Server D-Bus services should not be killed
-	 * because other programs may be using them.  The alarm daemon is
-	 * an autostart program now and Evolution no longer spawns it, so
-	 * that should not be killed either.  The only thing left to do
-	 * really is shoot ourselves. */
-
-	/* XXX Maybe --force-shutdown should be deprecated. */
-
-	program = g_find_program_in_path ("pkill");
-
-	if (program == NULL) {
-		g_printerr ("Could not find `pkill' program in path.\n");
-		exit (1);
-	}
-
-	/* This does not return. */
-	execl (program, "pkill", "evolution", NULL);
+	filename = g_build_filename (EVOLUTION_TOOLSDIR, "killev", NULL);
+	execl (filename, "killev", NULL);
 
 	g_assert_not_reached ();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]