summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/gdm-common.c48
-rw-r--r--common/gdm-common.h2
-rw-r--r--daemon/gdm-session-worker-job.c2
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");