[gdm/multi-stack: 26/35] KILL stuck processes if they don't die on TERM



commit 0e1bbc53dc248b31f19de2436251a09fc7133d87
Author: Ray Strode <rstrode redhat com>
Date:   Fri Jul 24 14:41:48 2009 -0400

    KILL stuck processes if they don't die on TERM
    
    Some PAM modules are really slow to shut down.
    We need to handle them being slow to shut down better,
    (by not blocking login on them shutting down etc), but
    in the mean time force them to die immediately.
    
    This is a temporary hack.

 common/gdm-common.c             |   48 ++++++++++++++++++++++++++++++++++++--
 common/gdm-common.h             |    2 +
 daemon/gdm-session-worker-job.c |    2 +-
 3 files changed, 48 insertions(+), 4 deletions(-)
---
diff --git a/common/gdm-common.c b/common/gdm-common.c
index adc42e6..0ffe802 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -93,13 +93,25 @@ gdm_get_pwent_for_name (const char     *name,
 }
 
 int
-gdm_wait_on_pid (int pid)
+gdm_wait_on_and_kill_pid (int pid,
+                          int timeout)
 {
         int status;
-
+        int ret;
+        int num_tries;
+        int flags;
+
+        if (timeout > 0) {
+                flags = WNOHANG;
+                num_tries = 10 * timeout;
+        } else {
+                flags = 0;
+                num_tries = 0;
+        }
  wait_again:
         errno = 0;
-        if (waitpid (pid, &status, 0) < 0) {
+        ret = waitpid (pid, &status, flags);
+        if (ret < 0) {
                 if (errno == EINTR) {
                         goto wait_again;
                 } else if (errno == ECHILD) {
@@ -107,6 +119,30 @@ gdm_wait_on_pid (int pid)
                 } else {
                         g_debug ("GdmCommon: waitpid () should not fail");
                 }
+        } else if (ret == 0) {
+                num_tries--;
+
+                if (num_tries > 0) {
+                        g_usleep (G_USEC_PER_SEC / 10);
+                } else {
+                        char *path;
+                        char *command;
+
+                        path = g_strdup_printf ("/proc/%ld/cmdline", (long) pid);
+                        if (g_file_get_contents (path, &command, NULL, NULL)) {;
+                                g_debug ("GdmCommon: process (pid:%d, command '%s') isn't dying, now killing it.",
+                                         (int) pid, command);
+                                g_free (command);
+                        } else {
+                                g_debug ("GdmCommon: process (pid:%d) isn't dying, now killing it.",
+                                         (int) pid);
+                        }
+                        g_free (path);
+
+                        kill (pid, SIGKILL);
+                        flags = 0;
+                }
+                goto wait_again;
         }
 
         g_debug ("GdmCommon: process (pid:%d) done (%s:%d)",
@@ -122,6 +158,12 @@ gdm_wait_on_pid (int pid)
 }
 
 int
+gdm_wait_on_pid (int pid)
+{
+    return gdm_wait_on_and_kill_pid (pid, 0);
+}
+
+int
 gdm_signal_pid (int pid,
                 int signal)
 {
diff --git a/common/gdm-common.h b/common/gdm-common.h
index ae7469e..0efead3 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -32,6 +32,8 @@ gboolean       gdm_is_version_unstable            (void);
 void           gdm_set_fatal_warnings_if_unstable (void);
 
 int            gdm_wait_on_pid           (int pid);
+int            gdm_wait_on_and_kill_pid  (int pid,
+                                          int timeout);
 int            gdm_signal_pid            (int pid,
                                           int signal);
 gboolean       gdm_get_pwent_for_name    (const char     *name,
diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c
index be85f30..8b93663 100644
--- a/daemon/gdm-session-worker-job.c
+++ b/daemon/gdm-session-worker-job.c
@@ -296,7 +296,7 @@ session_worker_job_died (GdmSessionWorkerJob *session_worker_job)
         int exit_status;
 
         g_debug ("GdmSessionWorkerJob: Waiting on process %d", session_worker_job->priv->pid);
-        exit_status = gdm_wait_on_pid (session_worker_job->priv->pid);
+        exit_status = gdm_wait_on_and_kill_pid (session_worker_job->priv->pid, 3);
 
         if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
                 g_debug ("GdmSessionWorkerJob: Wait on child process failed");



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