Skip to content

Console: keep the Linux console reader alive when stdin becomes non-blocking - #1277

Open
berkleblebiciii wants to merge 2 commits into
openmultiplayer:masterfrom
berkleblebiciii:fix/1268-console-nonblocking-stdin
Open

berkleblebiciii wants to merge 2 commits into
openmultiplayer:masterfrom
berkleblebiciii:fix/1268-console-nonblocking-stdin

Conversation

@berkleblebiciii

@berkleblebiciii berkleblebiciii commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

On Linux, the server console permanently stops executing commands after a plugin or component puts stdin (fd 0) into non-blocking mode - for example a component embedding node.js, where node:process / libuv switches stdin to non-blocking. The console still echoes keystrokes, but no command is ever executed and not even Unknown command or variable: is printed. Windows is unaffected.

Root cause

The console reader thread does:

while (true)
{
    if (std::getline(std::wcin, line) && threadData->valid)
    {
        ...dispatch command...
    }
    else
    {
        threadData->isRunning = false;
        return;   // <- reader thread dies forever
    }
}

With fd 0 in non-blocking mode the underlying read() fails with EAGAIN, std::getline sets failbit, and the thread treats it as EOF and exits permanently. The stream stays in the failed state, so nothing is ever read again.

Fix

On the failure path, when the thread is still valid, check fd 0's status flags: if O_NONBLOCK is set, restore blocking mode, clear() the stream state and retry. Real EOF (stdin closed while blocking) still ends the thread exactly as before, so shutdown behaviour is unchanged.

Tested with a node.js-embedding component running:

import process from "node:process";
process.stdin.on('data', (chunk) => { console.log(`Received data: ${chunk}`); });

Before: first console input printed Unknown command or variable: foo, after that the console never responded again. After the fix the console keeps working.

Fixes #1268

…locking

If a plugin or component (one embedding node.js for example) puts fd 0 in
non-blocking mode, the reader thread's `read()` fails with EAGAIN,
`std::getline(std::wcin, ...)` sets failbit, and the thread exits
permanently - the console then only echoes input and never runs commands
again.  Detect that case, restore the blocking mode on fd 0 and retry.
Real EOF (stdin closed while blocking) still ends the thread as before.

Fixes openmultiplayer#1268
@NexiusTailer

Copy link
Copy Markdown
Contributor

How its different to this one? In which ways it's better than the already suggested method?

@AmyrAhmady
AmyrAhmady force-pushed the fix/1268-console-nonblocking-stdin branch from a130c03 to c01565d Compare October 10, 2026 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Console reader permanently dies on Linux when fd 0 becomes non-blockin

3 participants