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.
This commit is contained in:
@ -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
|
||||
|
||||
158
shell/killev.c
Normal file
158
shell/killev.c
Normal file
@ -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;
|
||||
}
|
||||
22
shell/main.c
22
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 ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user