[gjs] Fix gjs_crash_after_timeout() problems
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gjs] Fix gjs_crash_after_timeout() problems
- Date: Tue, 25 Aug 2009 17:21:46 +0000 (UTC)
commit 4175f42adf28325c65a6cb3ab8dea625e14dcdfa
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Mon Aug 24 21:14:40 2009 -0400
Fix gjs_crash_after_timeout() problems
Fix two major issues with gjs_crash_after_timeout():
* It didn't notice the parent exiting normally so the forked off
child would keep running until the timeout. This is fixed by
using a pipe between the parent and child and watching for the
pipe to get immediate notification of parent exit.
* The forked off child process would return to the caller of
gjs_crash_after_timeout() after the timeout completed and it
killed the parent this would typically fail horribly. Call exit()
instead.
http://bugzilla.gnome.org/show_bug.cgi?id=592962
util/crash.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 58 insertions(+), 4 deletions(-)
---
diff --git a/util/crash.c b/util/crash.c
index 81328d5..101f094 100644
--- a/util/crash.c
+++ b/util/crash.c
@@ -32,6 +32,8 @@
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
@@ -133,7 +135,31 @@ void
gjs_crash_after_timeout(int seconds)
{
pid_t parent_pid;
- guint remaining;
+ int pipe_fds[2];
+ fd_set read_fds;
+ struct timeval term_time;
+ struct timeval remaining;
+ struct timeval now;
+ int old_flags;
+
+ /* We use a pipe to know in the child when the parent exited */
+ if (pipe(pipe_fds) != 0) {
+ fprintf(stderr, "Failed to create pipe to crash-in-timeout process: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ /* We want pipe_fds[1] to only be open in the parent process; when it closes
+ * the child will see an EOF. Setting FD_CLOEXEC is protection in case the
+ * parent spawns off some process without properly closing fds.
+ */
+ old_flags = fcntl(pipe_fds[1], F_GETFD);
+ if (old_flags == -1 ||
+ fcntl(pipe_fds[1], F_SETFD, old_flags | FD_CLOEXEC) != 0) {
+ fprintf(stderr, "Couldn't make crash-timeout pipe FD_CLOEXEC: %s\n",
+ strerror(errno));
+ return;
+ }
parent_pid = getpid();
@@ -147,12 +173,38 @@ gjs_crash_after_timeout(int seconds)
break;
default:
/* parent */
+ close(pipe_fds[0]);
return;
}
- remaining = seconds;
- while ((remaining = sleep(remaining)) > 0) {
- /* empty */
+ close (pipe_fds[1]);
+
+ gettimeofday (&now, NULL);
+
+ term_time = now;
+ term_time.tv_sec += seconds;
+
+ FD_ZERO(&read_fds);
+ FD_SET(pipe_fds[0], &read_fds);
+
+ while (TRUE) {
+ remaining.tv_sec = term_time.tv_sec - now.tv_sec;
+ remaining.tv_usec = term_time.tv_usec - now.tv_usec;
+ if (remaining.tv_usec < 0) {
+ remaining.tv_usec += 1000;
+ remaining.tv_sec -= 1;
+ }
+
+ if (remaining.tv_sec < 0) /* expired */
+ break;
+
+ select(pipe_fds[0] + 1, &read_fds, NULL, NULL, &remaining);
+ if (FD_ISSET(pipe_fds[0], &read_fds)) {
+ /* The parent exited */
+ _exit(0);
+ }
+
+ gettimeofday(&now, NULL);
}
if (kill(parent_pid, 0) == 0) {
@@ -160,5 +212,7 @@ gjs_crash_after_timeout(int seconds)
seconds, (int) parent_pid);
kill(parent_pid, SIGABRT);
}
+
+ _exit(1);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]