summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@benzedrine.nwnk.net>2007-09-11 11:37:06 -0400
committerDonnie Berkholz <dberkholz@gentoo.org>2008-05-06 20:55:15 -0700
commit6a5066c2e9e872d4ef85ec70745c34d93580177e (patch)
treed102686b65872430be784f50ddc24ee4638b5d9f
parentff4006bd5a71d39cc5655679447c5c47a99a2751 (diff)
Ignore - not just block - SIGALRM around Popen()/Pclose().
Because our "popen" implementation uses stdio, and because nobody's stdio library is capable of surviving signals, we need to make absolutely sure that we hide the SIGALRM from the smart scheduler. Otherwise, when you open a menu in openoffice, and it recompiles XKB to deal with the accelerators, and you popen xkbcomp because we suck, then the scheduler will tell you you're taking forever doing something stupid, and the wait() code will get confused, and input will hang and your CPU usage slams to 100%. Down, not across.
-rw-r--r--os/utils.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/os/utils.c b/os/utils.c
index 3bb7dbeba..afcaae41b 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1720,6 +1720,8 @@ static struct pid {
int pid;
} *pidlist;
+static sighandler_t old_alarm = NULL; /* XXX horrible awful hack */
+
pointer
Popen(char *command, char *type)
{
@@ -1741,11 +1743,15 @@ Popen(char *command, char *type)
return NULL;
}
+ /* Ignore the smart scheduler while this is going on */
+ old_alarm = signal(SIGALRM, SIG_IGN);
+
switch (pid = fork()) {
case -1: /* error */
close(pdes[0]);
close(pdes[1]);
xfree(cur);
+ signal(SIGALRM, old_alarm);
return NULL;
case 0: /* child */
if (setgid(getgid()) == -1)
@@ -1921,6 +1927,8 @@ Pclose(pointer iop)
/* allow EINTR again */
OsReleaseSignals ();
+ signal(SIGALRM, old_alarm);
+
return pid == -1 ? -1 : pstat;
}