Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js socket.send( ) functions failing to complete before exit

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);
like image 546
Alexander Mills Avatar asked Apr 27 '15 21:04

Alexander Mills


People also ask

Why do sockets hang up?

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.

How do you exit a function in node JS?

exit() method is used to end the process which is running at the same time with an exit code in NodeJS.

Which function exits from the current NodeJS process?

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.

What is a socket hang up?

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.


1 Answers

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
});
like image 97
lxe Avatar answered Sep 28 '22 09:09

lxe