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


Reply via email to