Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cluster] Primary process closes socket sporadically in linux #51578

Open
pmadhur opened this issue Jan 27, 2024 · 2 comments
Open

[Cluster] Primary process closes socket sporadically in linux #51578

pmadhur opened this issue Jan 27, 2024 · 2 comments
Labels
cluster Issues and PRs related to the cluster subsystem.

Comments

@pmadhur
Copy link

pmadhur commented Jan 27, 2024

Version

20.3.0

Platform

Linux *** 6.5.0-15-generic #15~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 12 18:54:30 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

server.js

const http = require('http');
const cluster = require('cluster');
cluster.setupPrimary({
    exec: 'worker.js',
    //execArgv: ['--inspect'],
    //inspectPort: 12000,
    args: [],
    windowsHide: true
});
const worker = cluster.fork();

const server = http.createServer((request, response) => {
    let data = '';
    request.on('data', (chunk) => {
        data += chunk.toString();
    });
    request.on('end', () => {
        if (request.method === 'POST') {
            worker.send({ type: 'request', data: JSON.parse(data) }, response.socket);
        } else {
            response.end('ok');
        }
    });
});
server.listen(3000);

worker.js

process.on('message', (message, socket) => {
    if (message.type !== 'request' || socket == null) {
        return;
    }
    const data = JSON.stringify({
        result: {
            isWorker: true,
            inputData: message.data
        }
    });
    socket.write(`HTTP/1.1 200 OK\r\n`);
    socket.write(`Server: node-worker\r\n`);
    socket.write(`Content-Length: ${Buffer.byteLength(data)}\r\n`);
    socket.write(`Content-Type: application/json\r\n`);
    socket.write(`Connection: close\r\n`);
    socket.write(`\r\n`);
    socket.end(data);
});

Start node server

node server.js

Open a browser, navigate to http://localhost:3000, open devtools, and execute the following snippet:

const totalExecutions = 100;
let numberOfExecutions = totalExecutions;
let processed = 0;
while(--numberOfExecutions >= 0) {
    doFetch();
}


function doFetch() {
    const data = {
        action: 'test',
        data: {
            foo: 'bar'
        }
    }
    const fetchOptions = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
    }
    fetch('http://localhost:3000', fetchOptions).then(response=>{
        return response.json()
    }).then((result)=>{
        onProcessed(null, result);
    }).catch(error=>{
        onProcessed(error)
    });
}

function onProcessed(error, result) {
    ++processed;
    if (error !== null) {
        console.error(error);
    }
    if (processed === totalExecutions) {
        console.log('all done');
    }
}

How often does it reproduce? Is there a required condition?

Until node v20.2.0, it works as expected, i.e., primary process never closes the socket, from v20.3.0 onwards, it does not work as expected, primary process sometimes closes the socket. In some environments, if totalExecutions in above browser snippet is changed to 7, it reproduces the error consistently.

What is the expected behavior? Why is that the expected behavior?

As in node v20.2.0 (irrelevant of whether connection is close or keep-alive), primary process should never close the socket. In worker process, socket is closed (see the example worker.js above).

What do you see instead?

Primary process closes the socket and the client (browser) gets the following message:
Screenshot 2024-01-27 171724

Additional information

Basic Hardware Info:

memory 64KiB BIOS
memory 16GiB System Memory
memory 8GiB SODIMM DDR4 Synchronous 2400 MHz (0.4 ns)
memory 8GiB SODIMM DDR4 Synchronous 2400 MHz (0.4 ns)
memory 256KiB L1 cache
memory 1MiB L2 cache
memory 8MiB L3 cache
processor Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
disk 500GB NVMe disk

@pmadhur
Copy link
Author

pmadhur commented Jan 28, 2024

In v20.3.0, whenever the primary process closes the socket, the function socketOnEnd gets called. In v20.2.0, socketOnEnd is never called.
Screenshot 2024-01-28 094424

@kvakil kvakil added the cluster Issues and PRs related to the cluster subsystem. label Jan 30, 2024
@pmadhur pmadhur changed the title [Cluster] Primary process closes socket sporadically in docker environments [Cluster] Primary process closes socket sporadically in linux Feb 3, 2024
@pmadhur
Copy link
Author

pmadhur commented Feb 3, 2024

The issue is reproducible without any third party environments/modules on Ubuntu 22.04.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cluster Issues and PRs related to the cluster subsystem.
Projects
None yet
Development

No branches or pull requests

2 participants