Emacs lisp command calling node hello.js:
(call-process "node" nil t nil "hello.js")
Two variants of hello.js:
hello_1.js:
console.log('Hello world!');
Output:
Hello world!
0
hello_2.js:
console.log('Hello world!');
process.exit(5);
Output (no output from log statement!):
5
What is the reason that process.exit(5) causes output to be suppressed?
Notes:
I experienced the problem in GNU Emacs 24.3.1 (i386-mingw-nt5.1.2600) of
2013-03-17 on MARVIN in combination with Node.js v0.10.18, running on
Windows XP/SP3/32.
I tried EShell to execute the node command line: no output
process.exit() calls low level process.reallyExit(), which causes the problem:
no output
process.reallyExit() is implemented in C++:
void Exit(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
exit(args[0]->IntegerValue());
}
[...]
NODE_SET_METHOD(process, "reallyExit", Exit);
Phew, I figured it out myself. First of all, I discovered that a delay causes
the output to appear:
hello_3.js:
console.log('Hello world!');
setTimeout(function () {
process.exit(5);
}, 1000);
Output:
Hello world!
5
So I double checked Node.js documentation for console, and found:
The console functions are synchronous when the destination is a terminal or a
file (to avoid lost messages in case of premature exit) and asynchronous when
it's a pipe (to avoid blocking for long periods of time).
Then I decided to make sure that no pipe is used and wrote a batch script
hello_2.bat:
#ECHO OFF
node hello_2.js >test
TYPE test
Output when calling the script with (call-process "cmd.exe" nil t nil "/C"
"hello_2.bat"):
Hello world!
0
(return value is 0 instead of 5, but I don't care about that)
To answer my question:
It looks like call-process in Emacs on Windows uses a pipe for retrieving
output from programs.
As I also mentioned EShell: It does not seem to be recognized as a
terminal by Node.js on Windows, and possibly EShell internally uses call-process or
similar to run programs.
Detection of a pipe as destination for standard output causes console.log
to be run asynchronously.
process.exit(5) in Node.js on Windows seems to discard all scheduled
asynchronous tasks, and thus no output is generated.
This assumption is supported by the outcome of desperately directing output to a
pipe inside the Windows command prompt:
C:\Temp> node hello_2.js | MORE
C:\Temp>
Finally, I found out that the issue is known since about a year ago (as of September 2013).
Related
I have some of the console commands I would like to use from Emacs, namely ag. It works great in CMD or Far Manager. However when I use it from Emacs shell or eshell I run into a problem which may be (slight chance, though) ag-specific.
When I run shell and then run ag it returns result (help screen) immediately. If I run it searching for a line in files inside directory as ag needle, it hangs and doesn't return anything.
If I run it as ag needle . it returns result immediately, however missing file names and lines numbers, --color and -nogroup options do not affect the printed result in this case.
When I run it via shell-command it returns the correct result (with file names and line numbers). eshell has the same problem.
What do I need to do to make these commands work in shell and/or eshell ?
It's been noted in the answers to this question that Win32 has issues with subprocess buffering. Is there a way to fix it?
If I create a process from a cmd prompt using the start command (opening a new cmd) is it possible to redirect the stdout and stderr from that process back to the calling cmd?
If you want the output of the STARTed process to appear in the parent command console, then simply use the START /B option.
If you want to process the output of your command, then you should use FOR /F ... in ('someCommand') DO ... instead.
OK. I have yet to find a straightforward answer to this question. I didn't want to bog down my question with what I thought unnecessary detail but seeing as I'm being criticized for the lack of this I'll expand a bit here.
I want to automate the updating of FWs on our production line, so I've a python app that gets the FWs from ftp and then uses the processors flash tool via python subprocess command to upload it to the board's flash. OK for all but one of the tools.
The one tool seems to have a problem when it's not running in its own terminal, so I provide a start to the subprocess command string which allows it to run OK in its own terminal. However, I need the output from this other terminal for logging reasons.
A possible solution was to log stdout and stderr to file using >> or wintee and then poll this file via a thread in my original app (perhaps a rather convoluted solution to the question). However the tool also has a separate problem where it doesn't like any std redirection, so this doesn't work for me.
I need to redirect output & error streams from one Windows process (GNU make.exe executing armcc toolchain) to some filter written on perl. The command I am running is:
Make Release 2>&1 | c:\cygwin\bin\perl ../tools/armfilt.pl
The compilation process throws out some prints which should be put then to STDOUT after some modifications. But I encountered a problem: all prints generated by the make are actually postponed till end of the make's process and only then are shown to a user. So, my questions are:
Why has it happen? I have tried to change the second process (perl.exe) priority from "Normal" to "Above normal" but it didn't help...
How to overcome this problem?
I think that one of possible workarounds may be to send only STDERR prints to the perl (that is what I actually need), not STDOUT+STDERR. But I don't know how to do it in Windows.
The Microsoft explanation concerning pipe operator usage says:
The pipe operator (|) takes the output (by default, STDOUT) of one
command and directs it into the input (by default, STDIN) of another
command.
But how to change this default STDOUT piping is not explained. Is it possible at all?
After installing ack on Windows 7 64-bit (e.g. using StrawberryPerl), I can run ack from a cmd terminal in Windows.
However, if I try using ack in Emacs in Shell mode (i.e. in a M-x shell buffer), I get not output (all other cmd commands print correctly though).
Interestingly, if I run ack alone - i.e. with no arguments-, I get the ack usage information printed correctly. In other words, ack prints no output in my Emacs shell when I run it with arguments (even though ack should print hits for my queries, as I have checked under cmd).
The lack of output makes me think that ack is waiting for input (although I provide arguments to it). I tried the code snippet suggested here in my .emacs file (which seems to be designed to help ack when it's confused between searching in the file system or STDIN), but the problem still persists.
Any suggestions on how to fix this?
Thanks
ack is waiting on stdin, incorrectly thinking it is in filter mode. As a workaround, add <NUL to the end of the command, closing its stdin.
FYI - Running "ack" in the perl debugger, inside emacs shell on Windows, shows it stopping here:
main::print_matches_in_resource(c:/Strawberry/perl/site/bin/ack:454):
454: while ( <$fh> ) {
Have you checked ack.el?
That's what I use on Windows 7. It makes using ack easier. By default it suggests searching for the word at point. And you get the output through compile, so you can easily jump to the file and line containing the match.
I am feeling surprised by the difference between two seemingly identical scripts.
first.ps1:
"A"
if ($true) { "B" }
"C"
second.ps1:
"A"
if ($true) { "B"
}
"C"
Now open a CMD window, and run these scripts like this:
powershell - < first.ps1
powershell - < second.ps1
first produces:
A
B
C
while second produces just
A
This has to be a bug.
In the redirection under cmd.exe case, the function completes normally and correctly if the if and else blocks are individually all on one line:
$candidate = '.\foo.txt'
$current= '.\bar.txt'
"Comparison starts"
if ($(diff $(get-content $current) $(get-content $candidate)).length -gt 0){"There was a difference"}
else {"There was not a difference"}
"Comparison over"
But if either block is split up onto more than one line and that branch is taken, the script aborts with no warning/output.
I'd report this on the PowerShell feedback site (connect.microsoft.com).
Not sure why the redirection to input doesn't work, but if you just specify the script as an input argument to powershell, it seems to work:
C:\fa2>powershell.exe C:\fa2\tc.ps1
Comparison starts
There was a difference
Comparison over
Edit:
Yep, Jay proved it. The root problem is that Powershell does not support the '<' operator. I've been searching all day for some official documentaion on the web, but have not found it. I just occured to me to check some old notes, and I found a reference to this not being supported in v1. It only supports '>'.
I'll try to update if I find something more official than my memory. Leaving original text just for completnes.
I dont think the accepted answer is enitrely true here.
Take a look at Lee Holmes blog: link
He is one of the devs on the Powershell team, and wrote the Powershell Cookbook, just to give a little credence to his words.
I've run into this kind of problem with some complicated and archaic Bat scripts that relied on some funky fancy binary redirection. Powershell would run the Bat file, but at the point where the binary redirection took place it would just stop. Using [Process]:Start as described in the blog post worked wonderfully, and allowed me to parse the output of the Bat file like any other nicely behaved script to boot.
In your case I assume "diff" is an actuall exe and not a function, and its outputing binary and not text.
On a side note, I really don't see the need for redirecting the output of the script to Powershell like youre doing. Seems kind of counterproductive. You wrote a powershell script, seems like a waste not to use the paramter specifically provided to handle running input.
I don't think this is a bug. Try typing each of those lines in on the console and you will see what is happening. When you type and open bracket and don't close it, PowerShell goes into a multiline entering mode. To exit this mode, you need a closing bracket AND a blank line afterward. If you have a blank line before or after the "C" it should work.
Of course, maybe it is a bug and just has the same effect as multiline input. :)
I can't get this to work myself, powershell is ignoring what I send into it.