ceylon.process not mapping standard/error output/input nor exit code
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
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...
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
https://bugs.openjdk.java.net/browse/JDK-8023130 (java 7 but still confirmed to exist in latest java 8 as well)
So what precisely is the workaround for it? I looked at CeylonTool and I don't understand.
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.
Or we just wait for the bug to be fixed in the the JDK?
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
Sure, but I don't really understand what the fix would be.
@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?
@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?
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
FYI, the JDK fix seems to have been backported to JDK 7u60.
Phew. :-)
Gavin King [email protected] http://profiles.google.com/gavin.king http://ceylon-lang.org http://hibernate.org http://seamframework.org
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 .
Thanks for the information, I will test it with JDK 7u60 when available
@loicrouchon Can this issue now be closed?
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.
OK, thanks, I would like to know before the release.
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