I need to perform a cleanup action when the Node process exits.
I know I can use process.on('exit'), process.on('Unhandled|Rejected Exception') and process.on('<signal>') to listen such events.
However, I would like not bind any of this, for these reasons:
If I bind to process.on('exit'), I should not be doing any async operations, which is not reliable when you need to write out a message over a socket or a pipe (afaik).
If I bind to process.on('some exceptions'), I have to print the error like a normal node process. I don't want to reinvent the wheel.
If I bind process("SIGINT"), I have to exit the process manually. What if someone else is listening too, or what if I can't know the exit status of the node process?
Any idea what I should do?
In my particular use case I will spawn a server, and when Node exits, I need to send it a signal to tell it to quit. And I would like this to be as transparent as possible for the module-consumer.
Thanks!
Just let your client process hang up.
In your use case, you mention that you have a socket going from your nodejs module to your server, and you want to kill the server when the module exits because the server has nothing else to do. No matter which way you spin it, there is no foolproof way for a client to tell a server that it's done with them by sending a message (since the client can die unexpectedly), but when they die, any connections that they have opened will close (it might take a few minutes in the case of an unhandled exception, but they will eventually close).
As long as you keep the socket open, the server will be able to tell that the connection is still alive. No traffic need actually be passing between the two programs, but the server can tell all the same. And, when the socket is closed (because the other end has exited), the socket on the server will get the socket.on('end') event. At that point, the server can clean up resources, and its empty event loop will automatically shut it down.
Related
I have a question about how server.listen method keep node process running. Is there any setInterval method inside?
I have read answer in post How does `server.listen()` keep the node program running. But still didn't understand it.
Anyone know please explain to me. Thanks.
Node.js internally in libuv has some sort of counter of the number of open resources that are supposed to keep the process running. It's not only timers that count here. Any type of open TCP socket or listening server counts too as would other asynchronous operations such as an in-process file I/O operations. You can see calls in the node.js source to uv_ref() and uv_unref(). That's how code internal to node.js marks resources that should keep the process running or release them when done.
Whenever the event loop is empty meaning there is no pending event to run, node.js checks this counter in libuv and if it's zero, then it exits the process. If it's not zero, then something is still open that is supposed to keep the process running.
So, let's supposed you have an idle server running with a listening server and an empty event loop. The libuv counter will be non-zero so node.js does not exit the process. Now, some client tries to connect to your server. At the lowest level, the TCP interface of the OS notifies some native code in node.js that there's a client that just connected to your server. This native code then packages that up into a node.js event and adds it to the node.js event queue. That causes the libuv to wake up and process that event. It pulls it from the event queue and calls the JS callback associated with that event, cause some JS code in node.js to run. That will end up emitting an event on that server (of the eventEmitter type) which the JS code monitoring that server will receive and then JS code can start processing that incoming request.
So, at the lowest level, there is native code built into the TCP support in node.js that uses the OS-level TCP interface to get told by the OS that an incoming connection to your server has just been received. That gets translated into an event in the node.js event queue which causes the interpreter to run the Javascript callback associated with that event.
When that callback is done, node.js will again check the counter to see if the process should exit. Assuming the server is still running and has not has .unref() called on it which removes it from the counter, then node.js will see that there are still things running and the process should not exit.
It's running through the event loop.
Every time event loop is looking for any pending operation, the server.listen() operation come forward.
I am creating a library that will start a process which then forks child_processes; it's much like using the cluster module with a server, except in my case neither the parent/master nor the child_processes are servers.
What I need to do is be able to give the user the option of killing the process once the whole thing starts. The only way I know of doing this, is to have the parent process listen on a specific port. Then I can communicate with the parent process, and it can be responsible for killing the child_processes.
The one problem with this, is if the user runs two or more different process groups side-by-side, then I would have to increment the port that each one listens on, and then the user doesn't actually know what the ports are anymore.
Does anyone know about the problem I am trying to solve and is there a good solution for this situation?
If I end up listening on a specific port, should I use the net module from core Node? Probably the net.Socket() option https://nodejs.org/api/net.html#net_class_net_socket
Seems like I need to make this process into a server so that it can listen on a port and easily receive messages.
Just launch with child_process module and the child processes will terminate when the parent does.
Then send the parent a signal like SIGINT or SIGHUP or SIGKILL. See https://nodejs.org/api/process.html#process_signal_events
// Start reading from stdin so we don't exit.
process.stdin.resume();
process.on('SIGINT', () => {
console.log('Got SIGINT. Press Control-D to exit.');
});
I'm working with a Node library that doesn't explicitly close sockets after it's done with them. Instead it tries to clean up by deleting reference to the socket and letting them be garbage collected.
Googling is failing me: I don't think that is possible for the GC to clean up unclosed sockets. That is, I think that any socket descriptors will still be in use, from the OS's perspective.
Additionally, assuming that I as the library consumer have access to the socket objects, what is the best way for me to close them? I have played around with end(), close(), and destroy() with limited success. Sometimes they seem to block into perpetuity (end/destroy), and other times it seems like the callback is never made (close).
It could be due to the fact that your socket sent a FIN package and hangs up on the connection while waiting for the other end to send the FIN2 message. In cases when the socket on the other side is not nicely closed, your one won't receive any package, thus hanging up forever.
Actually, end sends a FIN packet and does not shutdown the socket.
A possible solution could be to wait for a while on it by means of setTimeout when you invoke the end function, then explicitly destroy it by means of the function destroy. This won't affect your socket if the other end has correctly closed the connection, otherwise it will force the shutdown and all resources should be released.
I'm using NodeJS to run a socket server (using socket.io). When a client connects, I want am opening and running a module which does a bunch of stuff. Even though I am careful to try and catch as much as possible, when this module throws an error, it obviously takes down the entire socket server with it.
Is there a way I can separate the two so if the connected clients module script fails, it doesn't necessarily take down the entire server?
I'm assuming this is what child process is for, but the documentation doesn't mention starting other node instances.
I'd obviously need to kill the process if the client disconnected too.
I'm assuming these modules you're talking about are JS code. If so, you might want to try the vm module. This lets you run code in a separate context, and also gives you the ability to do a try / catch around execution of the specific code.
You can run node as a separate process and watch the data go by using spawn, then watch the stderr/stdout/exit events to track any progress. Then kill can be used to kill the process if the client disconnects. You're going to have to map clients and spawned processes though so their disconnect event will trigger the process close properly.
Finally the uncaughtException event can be used as a "catch-all" for any missed exceptions, making it so that the server doesn't get completely killed (signals are a bit of an exception of course).
As the other poster noted, you could leverage the 'vm' module, but as you might be able to tell from the rest of the response, doing so adds significant complexity.
Also, from the 'vm' doc:
Note that running untrusted code is a tricky business requiring great care.
To prevent accidental global variable leakage, vm.runInNewContext is quite
useful, but safely running untrusted code requires a separate process.
While I'm sure you could run a new nodejs instance in a child process, the best practice here is to understand where your application can and will fail, and then program defensively to handle all possible error conditions.
If some part of your code "take(s) down the entire ... server", then you really to understand why this occurred and solve that problem rather than rely on another process to shield you from the work required to design and build a production-quality service.
Context: Linux (Ubuntu), C, ZeroMQ
I have a server which listens on ipc:// SUB ZeroMQ socket (which physically is a Unix domain socket).
I have a client which should connect to the socket, publish its message and disconnect.
The problem: If server is killed (or otherwise dies unnaturally), socket file stays in place. If client attempts to connect to this stale socket, it blocks in zmq_term().
I need to prevent client from blocking if server is not there, but guarantee delivery if server is alive but busy.
Assume that I can not track server lifetime by some external magic (e.g. by checking a PID file).
Any hints?
Non-portable solution seems to be to read /proc/net/unix and search there for a socket name.
Without showing your code all of this is guesswork... that said...
If you have a PUB/SUB pair, the PUB will hang around to make sure that its message gets through. Perhaps you're not using the right type of zmq pair. Sounds more like you have a REP/REQ pair instead.
This way, once you connect from the client (the REQ side), you can do a zmq_poll to determine if the socket is available for writing. If yes, then go ahead with your write, otherwise shutdown the client and handle the error condition (if it is an error in your system).
Maybe you can try to connect to the socket first, with your own native socket. If the connection succeeds, it's quite high possibility your publisher could work fine.
There is another solution. Don't use ipc:// sockets. Instead use something like tcp://127.0.0.101:10001. On most UNIXes that will be almost as fast as IPC because the OS recognizes that it is a local connection and shortcuts the full IP stack processing.