Skip to content

Commit 334d56d

Browse files
brandon-beacherry
authored andcommitted
Added external interface for signal handlers.
Also process.pid and node.kill().
1 parent 0283e68 commit 334d56d

File tree

4 files changed

+81
-36
lines changed

4 files changed

+81
-36
lines changed

doc/api.txt

+9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ These objects are available to all programs.
5353
+node.cwd()+::
5454
Returns the current working directory of the process.
5555

56+
+node.kill(pid, signal)+ ::
57+
See kill(2). The standard POSIX signals are defined under the +node+
58+
namespace (+node.SIGINT+, +node.SIGUSR1+, ...).
59+
5660
+node.compile(source, scriptOrigin)+::
5761
Just like +eval()+ except that you can specify a +scriptOrigin+ for better
5862
error reporting.
@@ -101,6 +105,9 @@ the global scope. +process+ is an instance of +node.EventEmitter+.
101105
+
102106
The parameter +code+ is the integer exit code
103107
passed to +process.exit()+.
108+
| +"SIGINT"+, +"SIGUSR1"+, ... | (none) | Emitted when the processes receives a signal.
109+
See sigaction(2) for a list of standard POSIX
110+
signal names such as SIGINT, SIGUSR1, etc.
104111
|=========================================================
105112

106113
+process.exit(code=0)+::
@@ -113,6 +120,8 @@ An array containing the command line arguments.
113120
+process.ENV+ ::
114121
An object containing the user environment. See environ(7).
115122

123+
+process.pid+ ::
124+
The PID of the process.
116125

117126
=== System module
118127

src/node.cc

+21
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,25 @@ v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
250250
return Undefined();
251251
}
252252

253+
v8::Handle<v8::Value> Kill(const v8::Arguments& args) {
254+
HandleScope scope;
255+
256+
if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsInt32()) {
257+
return ThrowException(Exception::Error(String::New("Bad argument.")));
258+
}
259+
260+
pid_t pid = args[0]->IntegerValue();
261+
int sig = args[1]->Int32Value();
262+
263+
int r = kill(pid, sig);
264+
265+
if (r != 0) {
266+
return ThrowException(Exception::Error(String::New(strerror(errno))));
267+
}
268+
269+
return Undefined();
270+
}
271+
253272
typedef void (*extInit)(Handle<Object> exports);
254273

255274
// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
@@ -420,12 +439,14 @@ static Local<Object> Load(int argc, char *argv[]) {
420439
}
421440
// assign process.ENV
422441
process->Set(String::NewSymbol("ENV"), env);
442+
process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
423443

424444
// define various internal methods
425445
NODE_SET_METHOD(node_obj, "compile", Compile);
426446
NODE_SET_METHOD(node_obj, "reallyExit", Exit);
427447
NODE_SET_METHOD(node_obj, "cwd", Cwd);
428448
NODE_SET_METHOD(node_obj, "dlopen", DLOpen);
449+
NODE_SET_METHOD(node_obj, "kill", Kill);
429450

430451
// Assign the EventEmitter. It was created in main().
431452
node_obj->Set(String::NewSymbol("EventEmitter"),

src/node.js

+19
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,25 @@ node.mixin = function() {
9898
return target;
9999
};
100100

101+
// Signal Handlers
102+
103+
(function () { // anonymous namespace
104+
105+
function isSignal (event) {
106+
return event.slice(0, 3) === 'SIG' && node.hasOwnProperty(event);
107+
};
108+
109+
process.addListener("newListener", function (event) {
110+
if (isSignal(event) && process.listeners(event).length === 0) {
111+
var handler = new node.SignalHandler(node[event]);
112+
handler.addListener("signal", function () {
113+
process.emit(event);
114+
});
115+
}
116+
});
117+
118+
})(); // anonymous namespace
119+
101120
// Timers
102121

103122
function setTimeout (callback, after) {

test/mjsunit/test-signal-handler.js

+32-36
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,34 @@
11
node.mixin(require("common.js"));
22

3-
if (process.ARGV[2] === "-child") {
4-
node.stdio.open();
5-
var handler = new node.SignalHandler(node.SIGUSR1);
6-
handler.addListener("signal", function() {
7-
node.stdio.write("handled SIGUSR1");
8-
setTimeout(function () {
9-
// Allow some time for the write to go through the pipez
10-
process.exit(0);
11-
}, 50);
12-
});
13-
debug("CHILD!!!");
14-
15-
} else {
16-
17-
var child = node.createChildProcess(ARGV[0], ['--', ARGV[1], '-child']);
18-
19-
var output = "";
20-
21-
child.addListener('output', function (chunk) {
22-
puts("Child (stdout) said: " + JSON.stringify(chunk));
23-
if (chunk) { output += chunk };
24-
});
25-
26-
child.addListener('error', function (chunk) {
27-
if (/CHILD!!!/.exec(chunk)) {
28-
puts("Sending SIGUSR1 to " + child.pid);
29-
child.kill(node.SIGUSR1)
30-
}
31-
puts("Child (stderr) said: " + JSON.stringify(chunk));
32-
});
33-
34-
process.addListener("exit", function () {
35-
assertEquals("handled SIGUSR1", output);
36-
});
37-
38-
}
3+
puts("process.pid: " + process.pid);
4+
5+
var first = 0,
6+
second = 0;
7+
8+
process.addListener('SIGUSR1', function () {
9+
puts("Interrupted by SIGUSR1");
10+
first += 1;
11+
});
12+
13+
process.addListener('SIGUSR1', function () {
14+
second += 1;
15+
setTimeout(function () {
16+
puts("End.");
17+
process.exit(0);
18+
}, 5);
19+
});
20+
21+
i = 0;
22+
setInterval(function () {
23+
puts("running process..." + ++i);
24+
25+
if (i == 5) {
26+
node.kill(process.pid, node.SIGUSR1);
27+
}
28+
}, 1);
29+
30+
31+
process.addListener("exit", function () {
32+
assertEquals(1, first);
33+
assertEquals(1, second);
34+
});

0 commit comments

Comments
 (0)