Skip to content
This repository

Can't do process.on('SIGINT' with 0.5.4 on windows #1553

Closed
Pita opened this Issue August 18, 2011 · 52 comments
Peter 'Pita' Martischka
Pita commented August 18, 2011

original issue is here https://github.com/Pita/etherpad-lite/issues/94

We get following error message:

E:\etherpad-lite-win\node>..\bin\node server.js
←[32m[2011-08-18 04:36:32.850] [INFO] console - ←[39mServer is listening at 0.0.
0.0:9001

node.js:205
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: No such module
at EventEmitter. (node.js:318:27)
at E:\etherpad-lite-win\node\server.js:384:13
at E:\etherpad-lite-win\node_modules\async\lib\async.js:484:34
at Array. (E:\etherpad-lite-win\node_modules\async\lib\async.js:4
08:34)
at EventEmitter._tickCallback (node.js:197:26)

E:\etherpad-lite-win\node>

is on SIGINT a unix specific thing? is there something similar for windows? or is this a bug

Peter 'Pita' Martischka
Pita commented August 18, 2011

this happend on windows xp btw

Bert Belder
Collaborator

SIGINT is not supported in windows indeed. It is possible to capture ctrl+c / ctrl+break on windows, but there is no support for this yet in node.

Adding event emitters should probably not crash node, but for the time being it might actually be good if it does.
@ry @bnoordhuis what do you guys think?

Ben Noordhuis

Catching Windows events and emitting them as SIGINT / SIGTERM signals through the process object seems like the best option from a backwards compatibility / cross compatibility point of view.

Peter Bright

I had almost forgotten about it, but this issue is the one that made me start making code contributions to Node.

Wyatt Anderson

Seems like a sensible way to accomplish this would be to have a win32-specific SignalWatcher object (since SignalWatcher isn't even included in the win32 build, as far as I can tell) that emulates signals in some appropriate fashion, right?

MSDN lists the "signals" a process can receive from the console, and maybe in combination with what can be received in normal conditions (process shutdown, etc.) emulate the POSIX equivalents.

The problems I see with this are twofold:
1. Coming up with a sensible translation between Windows process events and POSIX signals
2. It's probably more ideal to have some platform-independent abstraction for application/process state, perhaps in combination with what process.on already provides on Linux systems beyond stuff like SIGINT and SIGKILL.

Thoughts? Obviously not a member of the team or anything, but I've been contemplating a patch and wanted feedback.

Bert Belder
Collaborator

I agree that we'll need a way for node apps to capture console control signals. A patch should go into libuv - we haven't discussed this yet, but it seems obvious that we'll have to put a somewhat cross-platform equivalent of ev_signal in libuv.

Peter Bright
Bert Belder
Collaborator

@DrPizza
CTRL_CLOSE_EVENT != SIGTERM ?

Peter Bright
Wyatt Anderson

Python's signal seems to "do the right thing" for Windows:

On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other case.

Is the functionality in node_signal_handler.cpp being moved to libuv? That's what emits events on process, right?

Bert Belder
Collaborator

@wyattanderson
Did you verify it does the right thing? Is there any way you can use it in a meaningful way?

Peter Bright

SIGSEGV, SIGFPE, SIGILL are all SEH exceptions on Windows. We could feasibly install an SEH handler with e.g. AddVectoredExceptionHandler() that trapped these, but I'm not sure that we should.

SIGSEGV means there's a serious, possibly security-compromising, bug; crashing immediately is the only safe response.
SIGILL means that the compiler or V8 has a serious bug; crashing immediately is the only safe response.
SIGFPE means that V8 has a bug (since V8 should ensure FP is safe and handle any FP issues itself); crashing immediately is the only safe response.

SIGABRT would require abort() to co-operate and emit the signal. MSVC++ abort() doesn't co-operate and doesn't emit the signal; I have no idea what Python is doing to emulate it. I don't believe node gives any direct access to abort() anyway, so the value appears to be negligible to me.

SIGTERM should map to CTRL_CLOSE_EVENT, as @piscisaureus pointed out.


I think we can probably do something like this:
CTRL_C_EVENT -> SIGINT
CTRL_BREAK_EVENT -> SIGINT
CTRL_CLOSE_EVENT -> SIGTERM

CTRL_SHUTDOWN_EVENT and CTRL_LOGOFF_EVENT might be useful for services, but have no good signal that I know of. CTRL_SHUTDOWN_EVENT maps tolerably well to SIGTERM I suppose, but I'm not sure what to do with CTRL_LOGOFF_EVENT. Oh, apparently the documentation is wrong; CTRL_LOGOFF_EVENT is sent to any process on logoff. In that case, it too should become SIGTERM.

There might be some value in making CTRL_BREAK_EVENT do SIGHUP or something--that way, applications can use SIGHUP as a signal to reinitialize their configuration etc., which I believe some UNIX programs do.

Wyatt Anderson

Sounds good, @DrPizza. I like the idea of mapping CTRL_BREAK_EVENT to SIGHUP, too.

Peter Bright

As for the implementation... node_signal_watcher.cc currently uses libev directly. My assumption is that libev should be hidden behind libuv, just as libeio is being hidden.

There's the other side to the equation--kill() will have to be implemented to generate events for the ctrl-c handler. At the moment, node.cc calls kill() directly, inside a #ifdef __POSIX__. So I imagine this needs to be moved to libuv too.

ry

It seems java used SIGQUIT on unix to print debug information and CTRL_BREAK_EVENT on Windows. http://www.ibm.com/developerworks/java/library/i-signalhandling/

Other signals used by the JVM are for internal control purposes and do not cause it to terminate. The only control signal of interest is SIGQUIT (on Unix type platforms) and SIGBREAK (on Windows), which cause a Java core dump to be generated.

ry
ry commented October 04, 2011

We should get this in v0.6

James Howe

CTRL_C_EVENT -> SIGINT
CTRL_BREAK_EVENT -> SIGKILL
CTRL_CLOSE_EVENT -> SIGTERM
CTRL_LOGOFF_EVENT -> SIGHUP

is what seems most natural to me. Many tools I encounter on Windows use Ctrl+C to request a graceful shutdown, while Ctrl+Break is reserved for hard kills. CTRL_BREAK_EVENT -> SIGHUP seems a little unexpected.

Peter Bright
James Howe

But SIGHUP doesn't mean "please print some statistics and carry on" it means "console/tty has been closed".

People generally expect 'Break' to break execution.

Peter Bright
James Howe

I agree with making them distinguishable - hence my suggestions. Applications can assign handlers to do whatever they want (which is the original point of this issue), so all we have to worry about is having a logical mapping from Win32 to POSIX, without having to worry about what people might use them for.

Both the programs you cite only use this functionality in specific situations, not as a general rule.

Peter Bright
James Howe

Then map it to SIGUSR1.

Peter Bright
James Howe

Because a standard UNIX non-daemon wouldn't (and POSIX gives a different default action for SIGHUP). Further looking around the internet and the consensus seems to be that Ctrl+Break is equivalent to SIGQUIT (mostly based on the behaviour of Java, as you noted above).

Another question is whether to discourage users from trying to handle CTRL_CLOSE_EVENT (by mapping it to SIGKILL) or not (using SIGTERM or similar).

Peter Bright
Herbert Vojčík

@DrPizza "I know what SIGHUP means, but I do not actually care" But you should, or you end up giving wrong suggestions that may bring more bad than good. SIGHUP is unix equivalent of logout (hangup - hanging up the terminal line, legacy from the times where terminal was dialed and may get hang-up event, thus ending terminal session; hence, the nohup unix command to let the process survive SIGHUP). So it only natural that logout is mapped to SIGHUP and Ctrl+C is mapped to SIGUSR1.

(and don't ask me why they overloaded it with another meaning in case of daemons)

@OrangeDog: +1 to your list with SIGUSR1 amendment.

James Howe

Good point about SIGKILL, was getting confused with kill. I still think you're concentrating too much on 'UI event' -> 'Action user code should take' rather than 'UI event' -> 'Event we should emit'.

How about:
CTRL_C_EVENT -> SIGINT
CTRL_BREAK_EVENT -> SIGQUIT
CTRL_CLOSE_EVENT -> SIGTERM
CTRL_LOGOFF_EVENT -> SIGHUP

Peter Bright
Peter Bright
James Howe

@herby - I was being facetious. Though if that meant that Ctrl-Break caused the v8 interactive debugger to start...

@DrPizza - If node.js' goal is "scalable network programs", then being able to register it as a Windows service would be a good thing. But that's not within the scope of this issue.

Herbert Vojčík

@DrPizza sorry, I misread "I know what it means" as "I don't know what it means".

@OrangeDog whatever solution that is fine is fine :-)

ry
ry commented November 04, 2011

This is a missing API bug and we will full-fill it in v0.6.1 (or there abouts) but it's not making v0.6.0. Removing from v0.6 milestone.

Bert Belder
Collaborator

Just to keep everyone posted, the behavior that ctrl+break starts the debugger has been removed. To start the debugger, use node debug -p <<pid>> from another console.

Andy Burke

Although there's been lively argument above, this still seems an issue. I'm currently hitting it on windows in node 0.6.6. Personally, I don't care about what maps to SIGHUP. The thing stopping me right now is not being able to bind SIGINT.

Could this issue be broken into non-contentious and contentious parts and dealt with piecemeal?

James Howe

Priority order should be:

  1. Warn, don't crash when adding listeners
  2. Allow catching Ctrl+C as SIGINT
  3. The rest
Tim

Is this still a problem? Im running win 0.6.6

luffs

Still a problem in v0.6.9 (Win7x64)

Oleg Verych

I suggest managing processes by simple http server example, node has on its web site. This is not OS specific, doesn’t require node versioning. No need of PID files.

Any flexibility of SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGUSR* can be programmed inside that “process controlling channel”. Just some localhost privilege separation and auth will be needed.

Especially this is true when we see, that automation scripting in e.g. WSH has only Terminate() method to manage execution of a process by its PID (kill –KILL as I can see).

I.e. if SIG* stuff will be implemented under MS Windows, it will be a thing inside node itself anyway. And this will be NIH (from e.g. Cygwin)…

If other application must be managed, signals aren’t right thing to do also. I.e. mongodb has
{ "shutdown" : 1 } or db.shutdownServer().

James Howe

@olecom Not every Node program is am HTTP server. Also, a public webserver that terminates when you make a particular request is not a good idea.

Perl supports "signals" on Windows using exactly the same syntax as on *NIX (i.e. it's actually a portable platform), so I don't see why Node shouldn't too.

Tim

So this is not a node "0.5.4" version but more with windows and node. The title is a bit miss leading.

Alex Kocharin

If other application must be managed, signals aren’t right thing to do

It is the right thing to do because it is independent of other app API

Mongo has {"shutdown":1}. Does mysql or nginx have it? But SIGINT will shutdown them both.

Oleg Verych

Does mysql or nginx have it? But SIGINT will shutdown them both.

Right.
But that SIGINT must not be in node under MS Windows...
I say cygwin, others say perl, that's OK. Process management (start/stop, watchdogs, bin updates) must be done using external and solid tools. Under linux-gnu this are shell and perl. So....

Dane Springmeyer

just hit this with node 0.6.15

Kyle Alan Hale

As thrilling as these semantic discussions have been, we really need to finalize a way to monitor processes in all OSes using a consistent API. Cleaning up after worker processes when using cluster in Windows is impossible in some circumstances (such as stopping a run or debug session in WebStorm).

Ivan
Ivanca commented May 30, 2012

I little work around I found is to capture the STDIN and use process.exit() when Ctrl+C is pressed; and then just listen to process.on("exit")

if(process.platform === "win32"){
    var rint = require('readline').createInterface( process.stdin, {} ); 
    rint.input.on('keypress',function( char, key) {
        if(char === "\u0003"){
            process.exit();
        }               
    }); 
    require('tty').setRawMode(true);
}
penartur

@AltIvan That won't work when stdin has been redirected (e.g. node app.js < input.txt). I'm not sure whether it won't crash trying to attach to such a stream at all.

Ivan
Ivanca commented May 30, 2012

@penartur Yeah, I am sure it doesn't work in many situations, is just if you are doing something really simple and just want Ctrl+C to fire an event

Lance Hunt

I tossed-in an ugly try/catch around this issue for now, but it would be nice if node didnt blow chunks on this.

Ian Young iangreenleaf referenced this issue in isaacs/node-supervisor June 05, 2012
Closed

error "No such module" in windows #59

Sean McArthur

Agreed, less chunk-blowing would be preferable.

Dane Springmeyer

It appears that ea1cba6, which landed in v0.8.9, avoids the throw of 'no such module'

Ben Noordhuis

Yes, this should be solved now. Closing.

Ben Noordhuis bnoordhuis closed this September 13, 2012
dherman dcherman referenced this issue in rwaldron/johnny-five February 03, 2013
Closed

Windows - process.on( "SIGINT" ... ) #54

Evan Tahler evantahler referenced this issue in evantahler/actionhero March 02, 2013
Closed

Windows ctrl-c not stopping proper #124

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.