diff options
-rw-r--r-- | common/gdm-common.c | 48 | ||||
-rw-r--r-- | common/gdm-common.h | 2 | ||||
-rw-r--r-- | 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 de807000..7a4e26d8 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 8faeda5c..06300c8f 100644 --- a/common/gdm-common.h +++ b/common/gdm-common.h @@ -34,6 +34,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 50bf4c0a..c13a0a29 100644 --- a/daemon/gdm-session-worker-job.c +++ b/daemon/gdm-session-worker-job.c @@ -262,7 +262,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"); |