Understanding Standard I/O streams of processes and Runtime.Exec Divergent Shell behaviour

Hi, I have had problems with the java.Runtime API, namely with the exec method, which led me to discover a great javaworld article by Michael Daconta "When runtime .exec won't". This article both helped me a lot with my problems, but also brought some questions into my mind. I would like to: 1st: get some insight to some core principles of what happens when a process is launched in an OS - if it is a standard feature to give each process three standard I/O streams (input,output and error); 2nd: understand why the powershell.exe and cmd.exe, the two windows shells, seem to process their input arguments in different manners. When in the command prompt they show similar reactions. 1) In regard to runing applications, the author of the "When Runtime Won't" article, Michael Daconta, explained why process using the Exec method can be stopped forever when he executes the wait for method. Basically what he said was that: depending on the OS, the buffer streams (stdout, stdin, sstderr) can have limited size. Therefore, If the application is attempting to write to one of these buffers, and it is full: that application can get permanently locked. What I'd like to understand is this: whichever the application, no matter the computer language use, when an application runs: the OS automatically assigns that application 3 buffer streams? Is that it? Two for output of the application, and one for Input? And those buffers are totally independent from the rest of the applications? Or is it the Java Runtime Env that gives the application three buffer streams? If it is the OS, I wonder: how does a shell print the output of a command line program? Does It do the same thing as the Michael's gobblers did? That is: since the shell is the one ordering the launch of your application, metaphorically, that shell has access to your output streams and is constantly reading them and printing them to the screen? If so: Can't we say that a shell is a graphical application, it controls a screen menu and can dump content into that menu? Its only limitation, is that the applications whose outputstream it can sniff are those whose graphics are only text? In the end, If my application is producing some output and dumping it in some output stream, the only way any other application can read the output of mine if that second application knows precisely where to read it from. In case of the process that I launch through Runtime.Exec, I can get any of that application's buffers. So this tells me that: no matter the implementation language, each application if entitled to these buffers, and there are OS system calls that grant other applications access to these buffers. Moreover, when we type something on a shell? Whose input stream are we writing onto? Are we writing into the inputstream of the shell, or that of the application that is runing on top of the shell? It could be shell forwarding the input to our application's input stream. 2)On the second topic: the windows cmd.exe and powershell seem to process their input in totatlly different manners. And unfortunatly, this is not evidenced by the command prompt of each shell. The command prompt of each shell seems to work in similar manners. For istance, apssing an argument that involves spaces requirs one to place quotes. But my java application, when it passes the same argumetns to the two shells gets differents results. And I am not talking of the different internal commands that each shell supports: one has commanlets and the other has commands. I am talking of executing external OS applicaitons. For instance, one of my tests over both shells consisted on runing the TASKLIST application. In the command prompt of either shell, you could write: TASKLIST /FI "IMAGENAME eq cmd.exe" and this would work just fine. However, when I use the java exec. For the windows cmd.exe I just need to pass the following string: "cmd /C TASKLIST /FI \"IMAGENAME eq cmd.exe\" "

dummyStub.runShellCommand(ScriptRunner.SHELL.WINDOWS_CMD, new String[]{"TASKLIST", "/FI", "\"IMAGENAME eq cmd.exe\""});

That is: i am giving the shell the exact same string i would otherwise write on its command prompt. But for the powershell, I have to really escape the quote. In the above example, the quote is being escaped so that java preserves it on the string it creates. Nothing more, nothing less. But of the power shell, the string that java creates needs to be escaping the quote. That is: "cmd /C TASKLIST /FI \\\"IMAGENAME eq cmd.exe\\\" "

dummyStub.runShellCommand(ScriptRunner.SHELL.WINDOWS_POWER_SHELL, new String[]{"TASKLIST", "/FI", "\\\"IMAGENAME eq cmd.exe\\\""});

Why does this happen? How come powershell inputstream processes differently the input coming from the command prompt, and the command coming from java? By the way, although it is not shown here, the code that I wrote bellow this one, that which exist on the runShellCommand method, creates a string arrway where the first arguments are: "cmd", "/C" for cmd.exe and "powershell" for powershell.exe. Thanks for reading, and thanks for any explanations.

This story, "Understanding Standard I/O streams of processes and Runtime.Exec Divergent Shell behaviour" was originally published by JavaWorld.


Copyright © 2009 IDG Communications, Inc.

How to choose a low-code development platform