Don't deadlock when stderr is a non-draining pipe#2300
Merged
Conversation
When AetherSDR is launched from OpenDeck (or any other parent that captures stderr but doesn't drain it — Stream Deck "Run Command", systemd user services, GUI launchers), the ~64 KB pipe buffer fills after about 60 KB of debug output and the next fprintf(stderr, ...) blocks indefinitely. Worse, since #2284 the entire messageHandler ran under a global QMutex to serialize log-file writes, so once one thread blocked on stderr every other thread that called qDebug / qInfo / qWarning queued behind it on the mutex — full-app deadlock, no log output, threads sitting in futex_wait. Two changes: 1. Move the file write into a tighter scope so the mutex is only held across the QFile call. The fprintf is outside the mutex — even an unexpected stderr stall can no longer block other threads' log calls. 2. Skip the stderr mirror entirely when stderr is not a TTY. CLI launches keep their console output; Stream Deck / systemd-user / GUI launchers go straight to the log file. The log-file path is unchanged in both cases. isatty / fileno are POSIX; on Windows they live in <io.h> as _isatty / _fileno. Wrap accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When AetherSDR is launched from OpenDeck (or any other parent that
captures stderr but doesn't drain it — Stream Deck "Run Command",
systemd user services, GUI launchers), the ~64 KB pipe buffer fills
after about 60 KB of debug output and the next fprintf(stderr, ...)
blocks indefinitely. Worse, since #2284 the entire messageHandler
ran under a global QMutex to serialize log-file writes, so once one
thread blocked on stderr every other thread that called qDebug /
qInfo / qWarning queued behind it on the mutex — full-app deadlock,
no log output, threads sitting in futex_wait.
Two changes:
Move the file write into a tighter scope so the mutex is only
held across the QFile call. The fprintf is outside the mutex —
even an unexpected stderr stall can no longer block other threads'
log calls.
Skip the stderr mirror entirely when stderr is not a TTY. CLI
launches keep their console output; Stream Deck / systemd-user /
GUI launchers go straight to the log file. The log-file path is
unchanged in both cases.
isatty / fileno are POSIX; on Windows they live in <io.h> as
_isatty / _fileno. Wrap accordingly.
Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]