# How to Handle Process Termination Signals Like SIGTERM in Node.js Socket Connections

> Safely handle SIGTERM in Node.js socket connections. Learn how this application terminates child processes and cleans up partial downloads upon receiving termination signals.

- Repository: [Ahmed Ibrahim/Website-downloader](https://github.com/AhmadIbrahiim/Website-downloader)
- Tags: how-to-guide
- Published: 2026-07-08

---

**The application handles SIGTERM signals by listening for Socket.IO `disconnect` events in [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js) to kill child processes, while [`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js) listens for the exit event to remove partial downloads before the process fully terminates.**

The **AhmadIbrahiim/Website-downloader** repository implements a graceful shutdown mechanism for long-running background tasks. When a client disconnects or the server needs to terminate downloads, the system orchestrates cleanup between the socket layer and child process handlers to prevent orphaned `wget` processes and incomplete files.

## The Socket.IO Disconnect Handler

The termination flow begins in **[`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js)**, where the server reacts to network-level disconnections. When a client closes their browser or loses connection, Socket.IO fires the `disconnect` event, which serves as the primary trigger for sending SIGTERM signals to active child processes.

### Storing Process References

When a download starts, the socket instance stores references to both the **wget** and **archiver** processes. This attachment allows the disconnect handler to access and terminate these specific jobs later.

According to the source code in [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js) (lines 5-9), the application assigns spawned processes directly to the socket object:

```javascript
socket.wgetProcess = launchWget(data);
socket.archiverProcess = launchArchiver(data);

```

### Triggering SIGTERM on Disconnect

The `disconnect` event handler checks for attached processes and invokes the `.kill()` method, which sends **SIGTERM** by default. This implementation appears in [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js) (lines 11-22):

```javascript
socket.on('disconnect', () => {
  if (socket.wgetProcess) socket.wgetProcess.kill();   // Sends SIGTERM
  if (socket.archiverProcess) socket.archiverProcess.abort();
});

```

Using `socket.wgetProcess.kill()` without arguments explicitly transmits SIGTERM, giving the child process an opportunity to handle cleanup before the operating system forcefully terminates it.

## Handling SIGTERM in the wget Process

The **[`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js)** module creates the actual download child process and registers signal-specific listeners. This separation of concerns keeps the socket layer lightweight while concentrating cleanup logic in the module responsible for the file system operations.

### Listening for the Exit Event

When SIGTERM arrives, the Node.js `child_process` module emits an `exit` event containing the signal name. The handler in [`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js) (lines 48-54) checks for the `SIGTERM` string specifically:

```javascript
const child = exec(`wget -mkEpnp --no-if-modified-since ${data.website}`);

child.on('exit', (code, signal) => {
  if (signal === 'SIGTERM') {
    console.log('Process terminated');
    removePartiallyDownloadedFiles(website);
  }
});

```

This conditional check ensures that cleanup only runs when the process receives an intentional termination signal, distinguishing it from normal completion or crash exits.

### Cleaning Up Partial Downloads

The `removePartiallyDownloadedFiles()` function, defined in [`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js) (lines 56-64), synchronously deletes the partially downloaded folder created by `wget`. This prevents incomplete data from consuming disk space and ensures the system returns to a clean state before the process exits.

## Archiver Process Termination

While the wget process receives SIGTERM via the `.kill()` method, the archiver uses a higher-level abstraction. The same `disconnect` handler calls `socket.archiverProcess.abort()` (lines 18-21 in [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js)), which delegates termination logic to the archiver implementation rather than sending raw signals.

## Practical Implementation Example

Here is the complete flow for handling process termination signals in a Node.js Socket.IO application:

```javascript
// socket/socket.js
io.on('connection', socket => {
  socket.on('request', data => {
    // Spawn processes and store references on socket instance
    socket.wgetProcess = launchWget(data);
    socket.archiverProcess = launchArchiver(data);
  });

  // Handle termination signals on client disconnect
  socket.on('disconnect', () => {
    if (socket.wgetProcess) socket.wgetProcess.kill();   // Sends SIGTERM
    if (socket.archiverProcess) socket.archiverProcess.abort();
  });
});

```

```javascript
// wget/index.js
const { exec } = require('child_process');

function downloadWebsite(website) {
  const child = exec(`wget -mkEpnp ${website}`);
  
  child.on('exit', (code, signal) => {
    if (signal === 'SIGTERM') {
      console.log('SIGTERM received, cleaning up...');
      removePartiallyDownloadedFiles(website);
    }
  });
  
  return child;
}

```

This pattern ensures that whether a user closes their browser tab or the server administrator sends a SIGTERM signal, the system gracefully terminates downloads and removes temporary files.

## Summary

- **Signal Origin**: The Socket.IO `disconnect` event in [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js) triggers the termination chain.
- **SIGTERM Transmission**: Calling `socket.wgetProcess.kill()` sends SIGTERM to the wget child process.
- **Signal Handling**: [`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js) listens for the `exit` event and checks if `signal === 'SIGTERM'` to initiate cleanup.
- **File Cleanup**: The `removePartiallyDownloadedFiles()` function removes incomplete downloads to prevent disk pollution.
- **Archiver Handling**: The archiver process uses `abort()` rather than SIGTERM for graceful termination.

## Frequently Asked Questions

### What is the difference between SIGTERM and SIGKILL in Node.js?

**SIGTERM** (signal 15) requests graceful termination, allowing the process to run cleanup handlers before exiting, while **SIGKILL** (signal 9) forces immediate termination without cleanup. The Website-downloader uses SIGTERM via `.kill()` to ensure partial downloads are removed before the process exits.

### How does the socket keep track of active download processes?

The application stores child process references directly on the Socket.IO instance using `socket.wgetProcess` and `socket.archiverProcess`. This attachment ensures that when the `disconnect` event fires, the server has immediate access to terminate the specific processes associated with that client connection.

### Why does the wget module check for the SIGTERM signal specifically?

The `exit` event fires whenever a child process terminates, including normal completion (null signal) or crashes. By checking `if (signal === 'SIGTERM')` in [`wget/index.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/wget/index.js), the code distinguishes between a successful download and a manual termination, ensuring cleanup logic only runs when necessary.

### Can this pattern handle server shutdowns as well as client disconnects?

While the current implementation focuses on Socket.IO `disconnect` events, the same pattern applies to server shutdowns. You can extend [`socket/socket.js`](https://github.com/AhmadIbrahiim/Website-downloader/blob/main/socket/socket.js) to listen for `process.on('SIGTERM')` and iterate through all active socket connections to trigger the same cleanup sequence.