I'm using (and have tried both) node 0.10.3x and 0.11.x (and the node bleeding edge) and have an issue i'm hoping someone can shed some light on.
I'm embedding node into a Win32 GUI app (that is to say /Subsystem:Windows and wWinMain, rather than the default /subsystem:console). Windows applications do not setup a proper stderr, stdin, stdout handles. When node::Load() attempts to run, the application exits with either code 1 (for node 0.11) or code 8 (for node 0.10).
I've traced the problem down.
- It starts with libuv win/handle.c in the function uv_guess_handle (line 56) that returns a FILE_TYPE_UNKNOWN for the file descriptor 1 or 2 (stdout, or stderr) if the subsystem is compiled as "Windows".
- This is called when node::Load runs, specifically in, src/node.js the function createWritableStdioStream (
line 483) - The createWritableStdioStream causes an error to be thrown thats caught by node.cc (line 2182)
- The FatalException exits the application, since we're in a windows GUI application, we don't see this, as its printed to stderr.. which doesn't exist (making it incredibly difficult to track down).
- Other related files that are used in the stack trace, but does not seem relevant: tty_wrap (line 89)
I've tried a few solutions but to no success.
- Create a Windows console buffer when acting like a GUI app, this allows you to capture stdin/stdout for application running as a GUI. Unfortunately since lib win/handle.c (line 56) uses the low-level file descriptor and not the stdin/stdout stream, this has no effect as the console buffer simply replaced the stdin/stdout global streams, not the 0 & 1 FD descriptors.
- Tried redirecting stdin, stdout, stderr using named pipes with CreateNamedPipe. This also had no effect for the same reason as #1.
- Tried reopening the stream to re-assign them, this, no effect, see above.
- Looked into hiding the console window and just compiling with /subsystem:console, however this causes a "flicker" when the app loads, but does successfully fix the issue.
- Tried using AttachConsole to a "faked" child processes' console, the child process is a dummy process that is created with CreateProcess with the console attribute hidden. This "sort of" worked, but caused halting problems as the stdout/stdin are themselves unable to create a stream buffer for some reason.
- Tried simply closing or opening the low-level fd stdout/stderr; however this had no effect and threw assertion errors from Windows.
About to give up, I thought that SOMEONE, SOMEWHERE must have fixed this issue. I looked at applications that use node in a GUI app, and found two solutions:
- Node-webkit modifies node.js to create dummy handles for stdio if its on win32. This isn't optimal, as i'd like to be able to only force the dummy handles for stdin/stdout/stderr if there really isn't a console available.
- Atom and others seem to take the approach of second process launches, which creates a second process (of themselves) the first launched with a subsystem:windows, then relaunched with STARTUPINFO on CreateProcess set to hide the console (but launched as a console application). This isn't an optimal solution either, as I stated in #5 above, there are corner cases where the system cannot create a std stream but can deliver a valid file descriptor for the stream (it causes assertion errors in windows __open_oshandle, unsure why) Although it does seem to work for 95% of the use cases i've seen.
TL;DR: Node fails with no workaround if it can't find stdin/stdout, like in a GUI app.
My first question: Does anyone know of another alternate way of getting this to work that I haven't tried? I'd rather not submit a patch nor modify the node code as its upstream?
My second question: If I submit a patch for node to help alleviate these issues, would creating dummy stdin/stdout/stderr be the best solution, is there alternate approaches recommended if I need to modify node?
댓글 없음:
댓글 쓰기