Streams created by IO::popen must HUP/INT/QUIT the child process on close
-------------------------------------------------------------------------
Key: JRUBY-2790
URL: http://jira.codehaus.org/browse/JRUBY-2790
Project: JRuby
Issue Type: Bug
Components: Core Classes/Modules
Affects Versions: JRuby 1.1.3
Reporter: Charles Oliver Nutter
Assignee: Charles Oliver Nutter
Fix For: JRuby 1.1+
While investigating JRUBY-2661 I discovered that although we shut down the
write stream for popened subprocesses, we're not doing everything we're
supposed to to actually shut that process down on close. In our case, we just
close the out stream and then wait for the process to terminate. This only
works for processes that normally terminate when their input stream has been
closed. But for processes like "yes", the source of the hangups in JRUBY-2661,
closing the out stream isn't enough. So this example hangs waiting for 'yes' to
terminate:
{noformat}
jruby -e "io = IO.popen('yes', 'r'); io.close"
{noformat}
It turns out that Ruby also sends HUP+INT+QUIT to the process, to make sure it
knows it should shut down:
{noformat}
void
rb_syswait(pid)
int pid;
{
static int overriding;
#ifdef SIGHUP
RETSIGTYPE (*hfunc)_((int));
#endif
#ifdef SIGQUIT
RETSIGTYPE (*qfunc)_((int));
#endif
RETSIGTYPE (*ifunc)_((int));
int status;
int i, hooked = Qfalse;
if (!overriding) {
#ifdef SIGHUP
hfunc = signal(SIGHUP, SIG_IGN);
#endif
#ifdef SIGQUIT
qfunc = signal(SIGQUIT, SIG_IGN);
#endif
ifunc = signal(SIGINT, SIG_IGN);
overriding = Qtrue;
hooked = Qtrue;
}
do {
i = rb_waitpid(pid, &status, 0);
} while (i == -1 && errno == EINTR);
if (hooked) {
#ifdef SIGHUP
signal(SIGHUP, hfunc);
#endif
#ifdef SIGQUIT
signal(SIGQUIT, qfunc);
#endif
signal(SIGINT, ifunc);
overriding = Qfalse;
}
}
{noformat}
I tried to emulate this behavior by digging into the UNIXProcess object and
getting out the private pid field to use for a kill call, but it did not appear
to shut down the process correctly:
{noformat}
if (child.getClass().getSimpleName().equals("UNIXProcess")) {
try {
Field pidField = child.getClass().getDeclaredField("pid");
pidField.setAccessible(true);
int pid = pidField.getInt(child);
System.out.println(pid);
runtime.getPosix().kill(pid, 1);
runtime.getPosix().kill(pid, 2);
runtime.getPosix().kill(pid, 3);
} catch (Exception e) {
e.printStackTrace();
} finally {}
}
{noformat}
For now I have tagged the specs that launch "yes" as failing, and we'll have to
addess it post 1.1.3.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email