Quitting node.js gracefully - node.js

I'm reading through the excellent online book http://nodebeginner.org/ and trying out the simple code
var http = require("http");
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
Now I didn't know (and I still don't know!) how to shut down node.js gracefully, so I just went ctrl+z. Now each time I try to run node server.js I get the following error messages.
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: EADDRINUSE, Address already in use
at Server._doListen (net.js:1100:5)
at net.js:1071:14
at Object.lookup (dns.js:153:45)
at Server.listen (net.js:1065:20)
at Object.<anonymous> (/Users/Bob/server.js:7:4)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
at Module.load (module.js:334:31)
at Function._load (module.js:293:12)
at Array.<anonymous> (module.js:421:10)
So, two questions:
1) How do I shut down node.js gracefully?
2) How do I repair the mess I've created?

I currently use Node's event system to respond to signals. Here's how I use the Ctrl-C (SIGINT) signal in a program:
process.on( 'SIGINT', function() {
console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" );
// some other closing procedures go here
process.exit( );
})
You were getting the 'Address in Use' error because Ctrl-Z doesn't kill the program; it just suspends the process on a unix-like operating system and the node program you placed in the background was still bound to that port.
On Unix-like systems, [Control+Z] is the most common default keyboard
mapping for the key sequence that suspends a process (SIGTSTP).[3]
When entered by a user at their computer terminal, the currently
running foreground process is sent a SIGTSTP signal, which generally
causes the process to suspend its execution. The user can later
continue the process execution by typing the command 'fg' (short for
foreground) or by typing 'bg' (short for background) and furthermore
typing the command 'disown' to separate the background process from
the terminal.1
You would need to kill your processes by doing a kill <pid> or 'killall -9 node' or the like.

Use Ctrl+C to exit the node process gracefully
To clean up the mess depends on your platform, but basically you need to find the remains of the process in which node was running and kill it.
For example, on Unix: ps -ax | grep node will give you an entry like:
1039 ttys000 0:00.11 node index.js
where index.js is the name of your node file.
In this example, 1039 is the process id (yours will be different), so kill -9 1039 will end it, and you'll be able to bind to the port again.

As node.js is an event-driven runtime the most graceful exit is to exhaust the queue of pending events. When the event queue is empty the process will end. You can ensure the event queue is drained by doing things such as clearing any interval timers that are set and by closing down any servers with open socket connections. It gets trickier when using 3rd party modules because you are at the mercy of whether the module author has taken care to gracefully drain the pending events it created. This might not be the most practical way to exit a node.js process as you will spend a lot of effort tracking down 'leaked' pending events, but it is the most graceful I think.

Type either
process.exit()
or
.exit
to exit node gracefully.
Hitting Control + C twice will force an exit.

1) How do I shut down node.js gracefully?
Listening for a SIGINT signal. On Windows you need to listen for a ctrl-c with the readline module.
I've written my own solution to provide an application a graceful shutdown and the usage of domains: grace. It's worth to have a look.

Related

node-sass module install script does not exit when npm install is launched by Ruby's popen3

UPDATE 3: This problem appears to be a part of the module installation of node-sass. The stranded process has a working directory of ./node_modules/node-sass, and its command-line scripts/install.js resolves to a file within the module. Furthermore, the last line of output that reaches the console matches a line output by node-sass' scripts/install.js:
if (cachedBinary) {
console.log('Cached binary found at', cachedBinary);
fs.createReadStream(cachedBinary).pipe(fs.createWriteStream(binaryPath));
return;
}
This code does not have any issues when run from the command-line (i.e., simply issuing npm install at the command prompt with a blank node_modules directory), but when npm install is launched via popen3, it appears that the stream .pipe call here blocks indefinitely.
This is a head scratcher for me at the moment...
If I ^C the terminal where Ruby has launched these child processes, the interrupt makes it to the rogue process and causes it to terminate. However, forcing all the pipes closed (or simply terminating the parent process) does not cause the rogue node.exe to exit.
I contemplated an alternative version of popen3 that explicitly waits on the child process instead of just implicitly waiting for the streams to all come to an end, but while this does permit the calling side to proceed properly, the rogue child process still hangs around, and would interfere with subsequent invocations by holding an open handle to the ./node_modules/node-sass directory.
UPDATE 4: I have opened this bug report with the node-sass project: https://github.com/sass/node-sass/issues/2459
UPDATE: I'm pretty sure this is actually a Node issue. I tracked down the root cause of the hang, and it is that through a complex tree of child processes, npm install ultimately leaves behind an instance of node.exe that just sits there, apparently indefinitely, doing nothing, keeping the stdout and stderr pipes it has inherited open.
So, this leaves new questions:
Is there a way to make Node not leave behind a straggler process after an npm install completes?
Is there a way to explicitly wait for the direct child process of popen3 to exit, instead of waiting for the streams to end, and then possibly close the streams from the listening side to terminate the threads pumping the output?
UPDATE 2: I have reproduced the problem with this minimalist code:
Open3::popen3 "npm install" do |stdin, stdout, stderr, thr|
stdin.close
stdout.each_line { |l| puts l }
end
With this code, the rogue node.exe process (command-line: scripts/install.js) hangs around after the npm install completes. Terminating the process unblocks the popen3 call (by causing stdout to come to an end, so the each_line loop terminates), and ^Cing the Ruby code (when running in an IRB window) causes the rogue node.exe to terminate (following a line in the console output: => #<IO:(closed)>).
This only happens when the process is run through popen3; the identical npm install from a CMD prompt exits normally.
Original question:
I'm having a problem with popen3 in a Ruby script. It's hanging, but I'm pretty sure it's not any of the usual candidates. I've updated my call to popen3 with tons of annotation so that I can see in the console output what's going on. Here is how I'm making the call:
command_output_lines = []
lock = Mutex.new
exit_code = nil
Logger.log("[MAIN] beginning popen3 block")
Open3.popen3(command_w_params) do |stdin, stdout, stderr, thr|
Logger.log("[MAIN] closing stdin stream")
stdin.close
Logger.log("[MAIN] starting [STDOUT]")
stdout_thread = Thread.new do
Logger.log("[STDOUT] started")
begin
stdout.each_line do |stdout_line|
Logger.log("[STDOUT] got a line, acquiring lock")
lock.synchronize do
command_output_lines <<= stdout_line
Logger.log(stdout_line)
end
Logger.log("[STDOUT] lock released")
end
rescue Exception => e
Logger.log("[STDOUT] exception: #{e}")
end
Logger.log("[STDOUT] exiting")
end
Logger.log("[MAIN] starting [STDERR]")
stderr_thread = Thread.new do
Logger.log("[STDERR] started")
begin
stderr.each_line do |stderr_line|
Logger.log("[STDERR] got a line, acquiring lock")
lock.synchronize do
command_output_lines <<= "[STDERR] " + stderr_line
Logger.warn(stderr_line)
end
Logger.log("[STDERR] lock released")
end
rescue Exception => e
Logger.log("[STDERR] exception: #{e}")
end
Logger.log("[STDERR] exiting")
end
Logger.log("[MAIN] joining to [STDOUT]")
stdout_thread.join
Logger.log("[MAIN] joining to [STDERR]")
stderr_thread.join
Logger.log("[MAIN] threads joined, reading exit status")
exit_code = thr.value.exitstatus
end
Logger.log("[MAIN] popen3 block completed")
(Never mind what exactly Logger.log is; just know that it sends output to the console.)
Where I'm seeing the problem, command_w_params is equal to npm install, and this code is running in the context of a bundle exec rake TaskName.
When it reaches this code, I see the following console output:
[MAIN] beginning popen3 block
[MAIN] closing stdin stream
[MAIN] starting [STDOUT]
[MAIN] starting [STDERR]
[MAIN] joining to [STDOUT]
[STDOUT] started
[STDERR] started
[STDOUT] got a line, acquiring lock
[STDOUT] lock released
[STDOUT] got a line, acquiring lock
> node-sass#4.9.2 install C:\Users\Jonathan Gilbert\RepositoryName\ProjectName\node_modules\node-sass
[STDOUT] lock released
[STDOUT] got a line, acquiring lock
> node scripts/install.js
[STDOUT] lock released
[STDOUT] got a line, acquiring lock
[STDOUT] lock released
[STDOUT] got a line, acquiring lock
Cached binary found at C:\Users\Jonathan Gilbert\AppData\Roaming\npm-cache\node- sass\4.9.2\win32-x64-57_binding.node
[STDOUT] lock released
...and then it just hangs. At this point, I can see in Process Explorer that the child process has exited. There is nothing left but ruby.exe, but it just sits there indefinitely until it is explicitly cancelled. The two threads are still running, indicating that the stdout and stderr streams haven't signalled end-of-stream yet.
Now, often when people have a problem with popen3, it's because they're not reading both stdout and stderr simultaneously, and one or the other fills up its pipe buffer while the parent process is only paying attention to the other. But my code is using separate threads and keeping the pipe buffers empty.
Another problem I've seen come up is that the child process may be sticking around waiting for stdin to be closed, but in this case:
stdin is being closed.
The child process doesn't even exist any more.
Does anybody recognize these symptoms? Why are the stdout and stderr streams not hitting end-of-stream when the child process exits??

NodeJS: How to stop a web server?

I'm using the plugin gulp-server-livereload.
var server = require('gulp-server-livereload');
gulp.src(pathDir).pipe(server({
livereload: true,
directoryListing: true,
open: true,
port: 80
}));
How to stop the server?
I tried server.restart(), server.kill(), server.reset()
But always there are such errors:
Uncaught Error: listen EADDRINUSE 127.0.0.1:35729
at Object.exports._errnoException (util.js:1022:11)
at exports._exceptionWithHostPort (util.js:1045:20)
at Server._listen2 (net.js:1262:14)
at listen (net.js:1298:10)
at doListening (net.js:1397:7)
at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:62:16)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:81:1
0)
Please help me to solve my question or tell me another option how you can
implement what I need.
This error is occurring because of another process using the port. It is likely just a previous instance of this process, however it is possible that another application is using the port.
You will be unable to stop this using Node, as it is a process remaining from another run and processes do not have the permissions to 'manage' one another.
On Windows use task manager to kill the node process, on Mac you can use Activity Monitor, and on Unix/Linux you can use htop or similar.
Alternatively on Unix/Linux (incl. MacOS) you can use
sudo lsof -i :35729
to find the process id of the process ID using that port, then kill it:
kill -9 {PID}
To ensure your node server cleanly shuts down in future add event handlers:
process.on('SIGTERM', ..)
process.on('uncaughtException', ..)
and invoke code inside these to shut down your application.

abrtd: Node Process was killed by signal 6 (SIGABRT)

I am running a Node program that does a long running data migration job. After an hour is process, Node process terminates by Abrt daemon and creates core dump.
Looking into the reason I see this:
node process was killed by signal 6 (SIGABRT)
Any ideas why Node process is killed and how to deal with it?
It turned out to be MemoryLeak issue in Strong-Oracle module I am using. I have increased Nodejs process memory to run with 4G memory. Working fine now.

foreverjs turns process in STOPPED state instead of restarting

I have nodejs process that listens for an connection. I want to let foreverjs restart it on any connection error this way:
amqpConnection.on('error', function (err) {
console.error(err);
process.exit(1);
});
But this don't work. After error I see my process in this state:
~> forever list
info: Forever processes running
data: uid command script logfile
data: [0] OpQF /usr/bin/node my-script.js my-script-log.log STOPPED
Log file has connection error and two attempts to restart script.
error: Script restart attempt #2
{ [Error: connect ECONNREFUSED]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect' }
error: Forever detected script exited with code: 1
Why forever stops trying to restart my process?
I should have read warnings that forever prints!
Script that not stay running more than --minUptime (1000ms by default) considered "spinning". One should set --spinSleepTime to make spinning scripts to be restarted. When this parameter is omitted spinning script won't be restarted.
I have reproduced your problem and found that forever successfully restart your process if some delay (1sec) take place before process.exit.
It's look that forever don't restart process when it crash too fast.
setTimeout(function() {
process.exit(1);
}, 1000);

Kill NodeJS child processes

During development I make mistakes in my NodeJS project. Mistakes lead to an error message like this.
events.js:85
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE
at exports._errnoException (util.js:742:11)
at Server._listen2 (net.js:1148:14)
at listen (net.js:1170:10)
at net.js:1253:9
at dns.js:82:18
at process._tickCallback (node.js:343:11)
No problem, I hit ctrl+C and restart the process but I see some spawned child processes still active. How can I kill all processes spawned by the root process?
Sample code:
module.exports.start = function(options) {
gulp.watch(['*.js'], onServerRestart);
onServerRestart();
var server;
function onServerRestart(e) {
if (server) server.kill();
server = require('child_process').spawn("node", ['--harmony', './server.js'], {stdio: "inherit", cwd: process.cwd() });
};
};
Adding this
process.on('uncaughtException', function(err) {
console.log(err);
server.kill();
process.kill();
});
solves the problem. Any suggestions how to handle this in your app?
This means, even though you may think you exited all servers, one is indeed still running, and that maybe the server you are trying to access.
Therefore go to your terminal and type the following:
killall node
This should solve it.
BAM.

Resources