In some Node.js scripts that I have written, I notice that even if the last line is a synchronous call, sometimes it doesn't complete before Node.js exits.
I have never seen a console.log
statement fail to run/complete before exiting, but I have seen some other statements fail to complete before exiting, and I believe they are all synchronous. I could see why the callback of an async function would fail to fire of course in this case.
The code in question is a ZeroMQ .send()
call like so:
var zmq = require('zmq');
var pub = zmq.socket('pub');
pub.bindSync('tcp://127.0.0.1:5555');
setInterval(function(){
pub.send('polyglot');
},500);
The above code works as expected...but if I remove setInterval()
and just call it like this:
var zmq = require('zmq');
var pub = zmq.socket('pub');
pub.bindSync('tcp://127.0.0.1:5555');
pub.send('polyglot'); //this message does not get delivered before exit
process.exit(0);
...Then the message will not get delivered - the program will apparently exit before the pub.send()
call completes.
What is the best way to ensure a statement completes before exiting in Node.js ? Shutdown hooks would work here, but I am afraid that would just be masking the problem since you can't put everything that you need to ensure runs in a shutdown hook.
This problem can also be demonstrated this way:
if (typeof messageHandler[nameOfHandlerFunction] == 'function') {
reply.send('Success');
messageHandler[nameOfHandlerFunction](null, args);
} else {
reply.send('Failure'); //***this call might not complete before the error is thrown below.***
throw new Error('SmartConnect error: no handler for ZMQ message sent from Redis CSV uploader.');
}
I believe this is a legit/serious problem because a lot of programs just need to publish messages and then die, but how can we effectively ensure all messages get sent (though not necessarily received)?
EDIT: One (potential) way to fix this is to do:
socket.send('xyz');
socket.close(); // supposedly this will block until the above message is sent
process.exit(0);
When a socket hang up is thrown, one of two things happens: When you're a customer, When you send a request to a distant server as a client and don't get a response in a timely manner. This error is caused by the end of your socket.
exit() method is used to end the process which is running at the same time with an exit code in NodeJS.
exit() Function: This function tells Node. js to end the process which is running at the same time with an exit code. By calling this function Node. js will force the current process that's running to exit as soon as possible.
It means that socket does not send connection end event within the timeout period. If you are getting the request for cheerio via http. request (not http. get ). You have to call request.
Diving into zeromq.node, you can see what Socket.send
just pushes your data to _outgoing
:
this._outgoing.push([msg, flags]);
... and then calls _flush
iff zmq.ZMQ_SNDMORE is unset:
this._flush();
Looks like _flush
is actually doing the socket write. If _flush()
fails, it emits an error.
Edit:
I'm guessing calling pub.unbind()
before exiting, will force the _flush()
to be called:
pub.unbind('tcp://127.0.0.1:5555', function(err) {
if (err) console.log(err);
process.exit(0); // Probably not even needed
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With