Node.js: SIGINT sent from process.kill() can't be handled
Asked Answered
K

1

2

I'm using Node.js v0.10.31 on Windows 8.1 x64. I noticed that for a process (a node.js or python script) that handles the SIGINT handler, the handler is not called when the signal is sent from another node.js process by process.kill(PID, "SIGINT"), and thus causing it to terminate. However I indeed verified that the handlers are called if the SIGINT is sent by pressing CTRL-C in console.

Here's the Node.js script that handles SIGINT (CoffeeScript):

process.on 'SIGINT', -> console.log "SIGINT handled"
process.stdin.pipe(process.stdout)
console.log "PID: #{process.pid}"

Console Output:

PID: 6916
SIGINT handled        (this happens when pressing ctrl-c in console)
SIGINT handled        (this happens when pressing ctrl-c in console)
# process terminates when another process calls process.kill(6916, 'SIGINT')

And here's a python script that handles SIGINT, which is also killed unconditionally by node.js process.kill(PID, 'SIGINT'):

from signal import signal, SIGINT
import os
import time

def handler(signum, frame):
    print "signal handled:", signum,
    raise KeyboardInterrupt

signal(SIGINT, handler)

print "PID: ", os.getpid()
while True:
    try:
        time.sleep(1e6)
    except KeyboardInterrupt:
        print " KeyboardInterrupt handled"

Console output:

PID:  6440
signal handled:2 KeyboardInterrupt handled    (this happens when pressing ctrl-c in console)
signal handled:2 KeyboardInterrupt handled    (this happens when pressing ctrl-c in console)
# process terminated by another node.js script's process.kill(6440, 'SIGINT')

Why isn't the handler called?

Khedive answered 26/9, 2014 at 7:1 Comment(0)
K
2

It seems like it's not the problem of Node.js that sends SIGINT, but rather a Windows platform issue. That's because when I send SIGINT from a python program, it also unconditionally terminates the process that handles the SIGINT event:

os.kill(pid, signal.SIGINT)

Luckily Python documents this better:

os.kill(pid, sig)

Send signal sig to the process pid. Constants for the specific signals available on the host platform are defined in the signal module.

Windows: The signal.CTRL_C_EVENT and signal.CTRL_BREAK_EVENT signals are special signals which can only be sent to console processes which share a common console window, e.g., some subprocesses. Any other value for sig will cause the process to be unconditionally killed by the TerminateProcess API, and the exit code will be set to sig. The Windows version of kill() additionally takes process handles to be killed.

Khedive answered 26/9, 2014 at 7:10 Comment(4)
The underlying problem IMO is that Node.js and Python are trying to pretend that signals are a universal concept, rather than one specific to particular operating systems. It would probably be less confusing to the developer if the signal-related functions simply didn't exist in the Windows version, rather than existing but not behaving as expected.Jordon
@HarryJohnston Signals (at least SIGINT and some others) are universal concept. These are defined in the C standard library and should be supported by any plaftform.Khedive
C signals and UNIX signals aren't really the same thing. In particular, the C standard doesn't appear to require any sort of support for sending signals between processes, and indeed the Visual Studio implementation doesn't allow you to do so. (In UNIX, C signals are implemented using UNIX signals, and historically C signals were derived from UNIX signals, but conceptually they're distinct.)Jordon
Granted, by analogy to C, there's perhaps no reason not to implement signal() and raise() on Windows if they would be useful, though that sort of programming is kind of dated. I still think implementing kill() was a mistake. (For that matter, I think including signal and raise in the C standard library was a mistake, but if so it's one we're stuck with.)Jordon

© 2022 - 2024 — McMap. All rights reserved.