Node JS process exit?

Node.js Process

How does the Node JS process exit?

There are several factors that can cause the Node JS process to exit. Among these factors, some are preventable, such as the code throws an exception; some are not preventable, such as memory exhaustion. process global variable is an Event Emitter instance if the process elegant exit, process will distribute a exit event. Application code can listen to this event to do the final cleanup work.

The following table lists the factors that can cause the Node JS process to exit.

OperateFor example
Log out manuallyprocess.exit(1)
Uncaught exceptionthrow new Error()
Unhandled promise rejectionPromise.reject()
Unhandled error eventEventEmitter#emit('error')
Unprocessed signalkill <PROCESS_ID>

Take the initiative to exit

process.exit(code) is the most direct way to end the process. The code parameter is optional and can be any number between 0 and 255, and the default is 0. 0 means the process is executed successfully, and a number other than 0 means the process has failed to execute.

When process.exit()is used, the console will not have any output, if we want to be like console output in the process launched when some of the error description message, you need to output an error message is displayed before the call.

node --eval="process.exit(42)"
echo $?

The above code exits the NodeJS process directly, and there is no output information from the command line. When the user encounters a process exit, he cannot obtain valid error information.

function checkConfig(config) {
  if (!config.host) {
    console.error("Configuration is missing 'host' parameter!");
    process.exit(1);
  }
}

In the above code, we output a clear error message before the process exits.

process.exit() function is very powerful, but we should not use it in the tool library. If an error is encountered in the tool library, we should throw it in the form of an exception, so that the application code can decide how to handle the error.

Exceptions, Rejections and Emitted Errors

process.exit() It is very useful in scenarios such as application startup configuration checks, but it is not applicable when dealing with runtime exceptions, and we need other tools.

For example, when the application is processing an HTTP request, an error should not cause the process to terminate. Instead, we should return a response containing the error message.

ErrorThe class can contain data that describes the details of the error occurrence, such as call stack and error text. Normally we would define XXXError specific scene, these XXXError system inherited Errorclass.

When we use the throwkeyword or code logic error, an error will be thrown. At this point, the system call stack will be released, and each function will exit until it encounters a try/catch statement that wraps the current call. If there is no try/catch statement, the error will be considered an uncaught exception.

Typically, in NodeJS application, we will define a Error class codeattribute, as used to describe the specific error code error, the advantage of this is that the error code may be unique, while the error code that is readable. At the same time, we can also cooperate messageattributes to describe the specific error message.

When an uncaught exception is thrown, the console will print the call stack and the process exits with the exit status code 1.

/tmp/infohubblog.js:1
throw new TypeError('invalid value');
^
Error: invalid value
    at Object.<anonymous> (/tmp/infohubblog.js:2:11)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47

This console output information indicates an error occurred in the infohubblog.js first 11 in the second row.

Global variables process is Event Emitter instance, you can listen uncaughtException to handle these uncaught exception events. The following code shows how to use:

const logger = require("./lib/logger.js");
process.on("uncaughtException", (error) => {
  logger.send("An uncaught exception has occured", error, () => {
    console.error(error);
    process.exit(1);
  });
});

Promise Rejection is similar to throwing an exception. We can call reject()the function or asyncarriving rejected state is throwing an exception to the promise function. The functions of the following two pieces of code are similar.

Promise.reject(new Error("oh no"));
(async () => {
  throw new Error("oh no");
})();

Currently, in NodeJS 14, Promise Rejection will not cause the process to exit. In subsequent versions, Promise Rejection may cause the process to exit.

Below is a sample console output of an uncaught Promise Rejection.

(node:52298) UnhandledPromiseRejectionWarning: Error: oh no
    at Object.<anonymous> (/tmp/reject.js:1:16)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47
(node:52298) UnhandledPromiseRejectionWarning: Unhandled promise
  rejection. This error originated either by throwing inside of an
  async function without a catch block, or by rejecting a promise
  which was not handled with .catch().

We can listen unhandledRejection to handle Rejection uncaught event sample code is as follows:

process.on("unhandledRejection", (reason, promise) => {});

Event Emitter is a basic module in NodeJS, which is widely used. When the Event Emitter of the errorevent is not handled, Event Emitter will throw an error, and it will cause the process to exit. Below is errorthe console output of an Event Emitter .

events.js:306
    throw err; // Unhandled 'error' event
    ^
Error [ERR_UNHANDLED_ERROR]: Unhandled error. (undefined)
    at EventEmitter.emit (events.js:304:17)
    at Object.<anonymous> (/tmp/foo.js:1:40)
    ... TRUNCATED ...
    at internal/main/run_main_module.js:17:47 {
  code: 'ERR_UNHANDLED_ERROR',
  context: undefined
}

Therefore, when we use the Event Emitter to ensure monitor the errorevent, so that when an error occurs, you can enable applications to handle these errors, to avoid Ben collapse.

Signal

Signals are operational information and provide an inter-process communication mechanism. The signal is usually a number, but a character string can also be used to identify it. For example, SIGKILLidentification number 9. Different operating systems have different definitions of signals. The following table lists the basic common signal definitions.

namenumberCan it be handledNodeJS default behaviourThe meaning of the signal
SIGHUP1YesquitThe parent command line is closed
SIGINT2YesquitAttempt to interrupt the command line, ie Ctrl + C
SIGQUIT3YesquitTry to exit from the command line, ie Ctrl + Z
SIGKILL9NoquitForce process to exit
SIGUSR110YesStart the debuggerUser-defined signal
SIGUSR212YesquitUser-defined signal
SIGTERM15YesquitThe process exits gracefully
SIGSTOP19NoquitThe process is forcibly stopped

In this table, whether it can be processed indicates whether the signal can be received and processed by the process. The default behaviour of NodeJS represents the default action performed by the process after receiving this signal.

We can monitor these signals in the following ways.

console.log(`Process ID: ${process.pid}`);
process.on("SIGHUP", () => console.log("Received: SIGHUP"));
process.on("SIGINT", () => console.log("Received: SIGINT"));
setTimeout(() => {}, 5 * 60 * 1000); // keep process alive

Run a command line window this code, then press Ctrl + C, will not withdraw from the process at this time, but will receive a print one line in the console SIGINT log information signal. Create a new command line window, execute the following command, PROCESS_ID is the process ID output by the above program.

kill -s SIGHUP <PROCESS_ID>

By starting a new command line, we send the original to a program that processes SIGHUPthe signal, the original command line window will print a row received the SIGHUPlog information signal.

In NodeJS code, a process can also send signals to other processes. for example:

node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"

This code will also output a first command line window received the SIGHUPlog signal.

If we want to make the process of the first command-line window exit, we can use the following command to achieve.

kill -9 <PROCESS_ID>

In NodeJS, signals are usually used to control the graceful exit of the process. For example, in Kubernetes , when a pod exits, k8s will send a like process in the pod SIGTERM signals, and start a 30-second timer. The application has 30 seconds to close the connection, save data, etc. If after 30 seconds the process is still alive, k8s will send another SIGKILL to force the shutdown process.

summary

This article describes several factors that can cause a process to exit, namely:

  • Take the initiative to exit
  • Uncaught exception, unhandled promise rejection, unhandled Event Emitter error events
  • System signal

Be the first to comment on "Node JS process exit?"

Leave a comment

Your email address will not be published.


*