Makememo / Makememo/MemoAI

Live transcription stalls after ~40 min: whisper-server deadlocks because its stderr pipe is never drained

Open Beginner friendly
#430 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
No language data
Stars
1.1k
Forks
108
PR merge metrics
No merged PRs in 30d

Description

Version: Memo 1.8.7 (bundle com.memo.whisper), bundled whisper-server 1.8.6, model ggml-large-v3-turbo.bin
OS / HW: macOS 26.6.2 (25G83), MacBook Air M4, 16 GB
Mode: live/realtime transcription (microphone), language = zh, VAD off

Symptom

About 39–40 minutes into a live recording, transcription silently stops. The app does not crash and does not show an error; new segments never appear, the recording buffer (temp/memo//folders/default//recordings/tmp.pcm) stops growing, and the session is not written to storage/local.db. Nothing recovers until Memo is fully quit and relaunched. The bug reproduces on every long session; the exact minute depends on how much log output whisper-server has produced.

Root cause (verified on a live hang)

whisper-server is spawned with the default stdio (three pipes). The main process only attaches a listener to stdout:

const Ze = spawn(Ge, Qe); // Qe = ["-m", model, "-l", lang, "--host", "0.0.0.0", "--port", port]
Ze.stdout?.on("data", Ke => { console.log([server] stdout: ${Ke}) });
// no Ze.stderr listener anywhere for this child

(app.asar, the whisper startWhisperServer / server-manager code. The stderr?.on("data") handler that does exist belongs to MemoRecorderServer, not to whisper-server.)

whisper-server writes per-request logs to stderr (operator(): processing '...' (N samples, S sec) ..., timings, etc.). Because nobody reads the pipe, the kernel socket buffer fills up. netstat -f unix on the hung process showed the stderr socket with Recv-Q 65494 (64 KB, i.e. full).

The next fprintf(stderr, ...) inside the /inference handler blocks forever while holding the inference mutex. All other httplib worker threads then block on that mutex, so every subsequent request from Memo hangs, times out client-side, and the pipeline stalls.

Thread sample of the hung whisper-server (all 1705/1705 samples):

Thread_209138 (holder)
httplib::Server::routing -> main::$_2::operator() + 2336
fprintf -> vfprintf_l -> __xvprintf -> __sflush -> _swrite -> __write_nocancel <-- blocked on stderr (fd 2, unix socket)

Thread_209136..209144 (8 workers)
httplib::Server::routing -> main::$_2::operator() + 84
std::mutex::lock -> _pthread_mutex_firstfit_lock_wait -> __psynch_mutexwait <-- waiting for the mutex above

Thread_209135: httplib::Server::listen_internal -> __accept (still accepting, so the backlog grows)

TCP state at the same moment (port 9588): one connection ESTABLISHED with 80 KB unread in the server's Recv-Q, one in CLOSE_WAIT with 268 KB unread (the client had already given up on it), and curl http://127.0.0.1:9588/ timed out.

This is the classic Node child_process pitfall documented in the Node docs: if the parent never consumes a piped stdio stream, the child can block once the pipe buffer is full.

Fix suggestions

Any one of these resolves it:

Attach a consumer: Ze.stderr?.on("data", ...) (log it, or .resume() to discard).
Spawn with stdio: ["ignore", "pipe", "ignore"] (or "inherit" for stderr).
Redirect the child's stderr to a rotating log file so users can send it with bug reports (bonus: this would also have made the failure visible).

Also worth doing: on /inference timeout, restart the whisper-server child instead of leaving the session in a state where the UI looks alive but nothing is transcribed.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the whisper startWhisperServer/server-manager code in app.asar and inspect the spawn call and its existing stdout handling. Ensure whisper-server's stderr is consumed or redirected, then verify with a long live microphone recording that transcription continues past the failure point and the session is saved.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
audio-video-rtc, desktop
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.