ceylon-sdk icon indicating copy to clipboard operation
ceylon-sdk copied to clipboard

ceylon.process not mapping standard/error output/input nor exit code

Open loicrouchon opened this issue 12 years ago • 19 comments

Consider the following module.ceylon

module testprocess "1.0.0" {
    import ceylon.process "1.0.0";
}

and run.ceylon

import ceylon.process { createProcess, Input, currentOutput, currentInput, currentError, Process, Output, currentEnvironment, Error }
import ceylon.file { current, Path }

shared void run() {
    process.writeLine("testing process on windows");
    executeCommand("ceylon.bat run --run=testprocess.fail testprocess");
}

shared void fail() {
    process.writeLine("should be written on stdout");
    process.writeErrorLine("should be written on stderr");
    process.exit(42);
}

void executeCommand(
        String command,
        Path path = current,
        Input? input = currentInput,
        Output? output = currentOutput,
        Error? error = currentError,
        {<String->String>*} environment = currentEnvironment) {
    Process process = createProcess(command, path, input, output, error, *environment);
    process.waitForExit();
    print("command exit code: \"``command``\" = '``process.exitCode else "<null>"``'");
}

On windows, I would expect it to print:

testing process on windows
should be written on stdout
should be written on stderr
command exit code: "ceylon.bat run --run=testprocess.fail testprocess" = '42'

But it's not:

Here is the command line output:

testing process on windows
command exit code: "ceylon.bat run --run=testprocess.fail testprocess" = '0'

And the output when running it via eclipse:

testing process on windows
should be written on stdout
should be written on stderr
command exit code: "ceylon.bat run --run=testprocess.fail testprocess" = '0'

Using createProcess(command) instead of createProcess(command, current, currentInput, currentOnput, currentError, *currentEnvironment) returns for both command line launch and eclipse launch:

testing process on windows
command exit code: "ceylon.bat run --run=testprocess.fail testprocess" = '0'

On linux, it's seems to behave correctly when using createProcess(command, current, currentInput, currentOnput, currentError, *currentEnvironment).

Running ceylon.bat run --run=testprocess.fail testprocess in command line prints:

should be written on stdout
should be written on stderr

and exit code is

>echo %errorlevel%
42

So I suspect some input / ouput and exit code mapping problem on Windows in ceylon.process

loicrouchon avatar Nov 16 '13 10:11 loicrouchon

Well, @loicrouchon, I reviewed that code, and all I'm doing is calling the equivalent JDK API in java.lang.Process, so I don't see what I could possibly be doing wrong...

gavinking avatar Nov 20 '13 03:11 gavinking

There's a known problem with that API in Windows, see for example what we do in the CeylonTool: https://github.com/ceylon/ceylon-common/blob/ce186be04aaa1b13c61747a97acb15eacc6f55d8/src/com/redhat/ceylon/common/tools/CeylonTool.java#L365

quintesse avatar Nov 20 '13 09:11 quintesse

https://bugs.openjdk.java.net/browse/JDK-8023130 (java 7 but still confirmed to exist in latest java 8 as well)

quintesse avatar Nov 20 '13 09:11 quintesse

So what precisely is the workaround for it? I looked at CeylonTool and I don't understand.

gavinking avatar Nov 20 '13 13:11 gavinking

I don't know what the proper work-around is, for CeylonTool a partial fix was enough. The problem is that inherit just doesn't work, so you need a loop to pipe data from the parent's in to the child's and the other way around for out and err. I've seen some code that uses 3 threads for that. Seems a very heavy-handed solution though, but it might be necessary.

quintesse avatar Nov 20 '13 14:11 quintesse

Or we just wait for the bug to be fixed in the the JDK?

gavinking avatar Nov 20 '13 14:11 gavinking

Or we jOr we just wait for the bug to be fixed in the the JDK?ust wait for the bug to be fixed in the the JDK?

If we can a have a quick fix for it (not waiting JDK fix), it would be better because otherwise, ceylon.build is simply not usable on windows

loicrouchon avatar Nov 20 '13 14:11 loicrouchon

Sure, but I don't really understand what the fix would be.

gavinking avatar Nov 20 '13 14:11 gavinking

@quintesse Is the workaround just that, when running on win, @loicrouchon should provide his own I/O streams to the child processes, instead of inheriting the stdin/stdout of the parent process?

gavinking avatar Nov 20 '13 14:11 gavinking

@quintesse I took a look at your workaround in order to see if I can implement it in ceylon.build or if it can be implemented in ceylon.process, but as you said, only a partial fix was needed in your case (map std out).

So a complete fix would imply std in and std err too and in this case, threads are needed to handle those 3 streams at the same time. I did implement a sample workaround here: https://gist.github.com/loicrouchon/7719015 (but it doesn't cover the stdin pipe yet)

Question is, should this workaround be implemented in ceylon.process or in user-code (ceylon.build in my case)? @gavinking WDYT?

In any case, this doesn't solve the exit code problem. I'm still getting 0 out of both myProcess.waitForExit() and myProcess.exitCode when launching a new process running ceylon run xxx or ceylon run-js xxx

The funny thing is that this ceylon program when invoked from command line return the value passed to process.exit() but not when invoked via ceylon.process.

The java counterpart of this simple program does return value passed to System.exit() in command line and when invoked via ceylon.process.

program                                       cmd line    ceylon.process
------------------------------------------------------------------------
ceylon run program calling process.exit(42)         42                 0
ceylon run-s program calling process.exit(42)       42                 0
java program calling System.exit(42)                42                42

I didn't test other ceylon tools (compile, doc, ...) but it looks like there's a problem with ceylon tools. I think the exit code problem deserves its own issue in ceylon-compiler.

But before opening it, @quintesse could you confirm my analysis about exit code?

loicrouchon avatar Dec 01 '13 17:12 loicrouchon

FYI https://bugs.openjdk.java.net/browse/JDK-8023130 has been fixed in JDK 8, but not in JDK 7 :( So we'll have to implement a workaround for JDK 7 / windows

loicrouchon avatar Dec 01 '13 17:12 loicrouchon

FYI, the JDK fix seems to have been backported to JDK 7u60.

lucaswerkmeister avatar Jan 10 '14 11:01 lucaswerkmeister

Phew. :-)

Gavin King [email protected] http://profiles.google.com/gavin.king http://ceylon-lang.org http://hibernate.org http://seamframework.org

gavinking avatar Jan 10 '14 12:01 gavinking

That would be great, because having to work around it sucks :)

-Tako

On Fri, Jan 10, 2014 at 1:51 PM, Gavin King [email protected]:

Phew. :-)

Gavin King [email protected] http://profiles.google.com/gavin.king http://ceylon-lang.org http://hibernate.org http://seamframework.org

— Reply to this email directly or view it on GitHubhttps://github.com/ceylon/ceylon-sdk/issues/152#issuecomment-32024766 .

quintesse avatar Jan 10 '14 13:01 quintesse

Thanks for the information, I will test it with JDK 7u60 when available

loicrouchon avatar Jan 10 '14 18:01 loicrouchon

@loicrouchon Can this issue now be closed?

gavinking avatar Sep 19 '14 15:09 gavinking

I'm currently not able to check. I will test next week (when coming back) with the jdk including the fix if it's working Le 19 sept. 2014 17:26, "Gavin King" [email protected] a écrit :

@loicrouchon https://github.com/loicrouchon Can this issue now be closed?

— Reply to this email directly or view it on GitHub https://github.com/ceylon/ceylon-sdk/issues/152#issuecomment-56192319.

loicrouchon avatar Sep 19 '14 17:09 loicrouchon

OK, thanks, I would like to know before the release.

gavinking avatar Sep 19 '14 18:09 gavinking

Tested with JDK 1.7.0_67 and JDK 1.8.0

Now, inherits IO is working fine for stderr and stdout.

However, for exit code, it's still not working. process.waitForExit() and process.exitCode still returns 0 instead of 42. But if you launch the program doing the process.exit(42) in command line, you well have 42 returned by echo %errorlevel%.

Looks like the exit code problem wasn't part of https://bugs.openjdk.java.net/browse/JDK-8023130

loicrouchon avatar Sep 25 '14 18:09 loicrouchon