Command return codes
A typical UNIX command sets a return code when it completes to say whether it succeeded or failed. A C/C++ application calls the 'exit' function, and a Java application calls System.exit.
UNIX shells and other scripting languages rely on return codes at a pretty fundamental level. So if we want to implement a UNIX-like shell, we need to have a way to get return codes from JNode commands.
It appears that calling System.exit() from a JNode command should cause a VMExit exception to be thrown, holding the status value from the exit(int) call. I can catch this exception in the shell and snaffle the status value as a return code. However, there are some problems:
- It is not clear whether the current behaviour of System.exit() is by design, or whether its is a short term solution. Does anyone know?
- It seems that many JNode commands don't use exit to say that they have failed. Is this by design?
- What should happen if a 'child' thread of a JNode command calls exit()?
- Would a different 'standard way' for indicating JNode command failure be better; e.g. by the command throwing some distinguished exception?
- How should we handle uncaught exceptions? Should they be mapped to non-zero codes? (The analogy is that some UNIX signals are handed to the shell as part of the return code,)
Note: I don't want to make life difficult for shells, etc that don't need return codes. However, there does need to be some standardization of the shell / command nexus.
Please add your opinions below. I cannot get onto on IRC due to timezone differences. (Besides, there is no permanent record of JNode IRC discussions ... )
- Stephen Crawley's blog
- Login to post comments
Shells and isolates
Once isolates are working, running commands in their own isolates is the obvious way to go. For a start it is not possible to do "job control" (kill, stop, etc) reliably without isolates. (The old Thread.stop() etc methods are fundamentally unsafe, and Thread.interrupt() etc only work if the interrupted command is cooperating.)
However the overheads of isolates are potentially a concern, so there needs to be the option of running well-behaved commands in the current isolate.
I'd very much like for commands to not need to know if they are running in isolates. For example, if the 'standard' way for a command running in an isolate to set a return code is to call System.exit(), the same code should work when the command is launched some other way.
I'd also like for generic Java applications to be launchable as commands without modification. Since Java applications communicate with their environment via System.exit(), System.getProperty(), System.in/out/err etc, the shell needs to play nicely with these mechanisms. The easy answer is to run all non-native applications in isolates, but it is also possible to implement the above methods to dispatch to per-command state, streams, etc.
Isolates
Most of the issues raised here cannot be propperly addressed without isolates. An isolate would be a JNode proccess and since the unix shell is completely orineted to processes isolates will be the response for a lot of cases.
But the question is that even if we had isolates should we execute all shell commands in thier own isolate? And the answere is probably no. Since Jnode is not UNIX when proting a jnode shell to it some tradeoffs should be made. We should think about the solution.
Regarding you more speciffic points:
- the current behaviour of Syste,.exit() is only a workaround.
- we will see what overhead isolates will bring but starting every command in a separate isolates looks like an overkill to me. And if they are not started in a separate isolate then they are started in the main JNode process where System.exit() would mean system halt by analogy with the stanadrd JVM behaviour.
- isolates are the right answere for stopping all threads that are started by a command. Alternatively we could think about some kind of JNode process concept where the threads started by a command could be held in a structure and stoped together when a call to System.exit() occurs. But this is does not provide static field isolation and it might create confusion.
- how about a shell variouable holding the thrown exception if the return code is not zero? The return code can be generated by the command invoker of your shell as zero if there was no exception and an other value otherwise, assuming that the command itself does not provide a return code (it wasn't running in a new isolate).
So lots of open questions here...
Regards, Levente
Processes and Isolates
I'm not sure about the amount of overhead we get with Isolation. But anyway I'm wondering if we shouldn't make any process an isolate. For a platformindependant console application you need to get the exit code anyway. So if we don't have one Isolate per process the JNode behaviour will differ from other OSes.