AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Low 48 Bitcoin

Only pause read in `PeerManager` `send_data` not `read_event`

Public commit record

What the developer wrote

Authored by Matt Corallo

95/100 · Strong
Only pause read in `PeerManager` `send_data` not `read_event`

We recently ran into a race condition on macOS where `read_event`
would return `Ok(true)` (implying reads should be paused) due to
many queued outbound messages but before the caller was able to
set the read-pause flag, the `send_data` calls to flush the
buffered messages completed. Thus, when the `read_event` caller got
scheduled again, the buffer was empty and we should be reading, but
it is finally processing the read-pause flag and we end up hanging,
unwilling to read messages and unable to learn that we should start
reading again as there are no messages to `send_data` for.

This should be fairly rare, but not unheard of - the `pause_read`
flag in `read_event` is calculated before handling the last
message, so there's some time between when its calculated and when
its returned. However, that has to race with multiple calls to
`send_data` to send all the pending messages, which all have to
complete before the `read_event` return happens. We've (as far as I
recall) never hit this in prod, but a benchmark HTLC-flood test
managed to hit it somewhat reliably within a few minutes on macOS
and when a synthetic few-ms sleep was added to each message
handling call.

Ultimately this is an issue with the API - we pause reads via a
returned flag but unpause them via a called method, creating two
independent "stream"s of pause/unpauses which can get out of sync.
Thus, here, we stick to a single "stream" of pause-read events from
`PeerManager` to user code via `send_data` calls, dropping the
read-pause flag return from `read_event` entirely.

Technically this adds risk that someone can flood us with enough
messages fast enough to bloat our outbound buffer for a peer before
`PeerManager::process_events` gets called and can flush the pause
flag via `read_event` calls to all descriptors. This isn't ideal
but it should still be relatively hard to do as `process_events`
calls are pretty quick and should be triggered immediately after
each `read_event` call completes.
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification
The short version

What changed, and why it matters

This commit fixes a race condition in how the Lightning networking code pauses and resumes reading from a peer's connection. Previously, the code could tell a caller to pause reading, but by the time the caller acted on it, the reason to pause had already gone away. This could leave a peer connection stuck: no new messages would be read, and because nothing was being sent either, there was no later signal to resume reading. The fix moves the pause/resume signal into the same path used to send data, so the two cannot get out of sync. The commit also notes a small new risk: a very fast message flood could briefly bloat memory before the next processing cycle pauses reads.

Recommended action

Review custom `SocketDescriptor` implementations outside the repository for compatibility with the new `send_data` signature and `continue_read` semantics. Ensure `process_events` is called promptly after `read_event` to limit memory bloat from queued outbound messages. Monitor for any hang regressions in high-throughput or macOS environments.

Security signals we found

01

Race condition between read pause signal and outbound buffer drain could cause connection hang/DoS

02

Read pause/resume logic moved into single `send_data` stream to prevent desynchronization

03

New DoS consideration noted: fast inbound message flood could bloat outbound buffer before `process_events` flushes pause flag

04

API-breaking change in `SocketDescriptor::send_data` semantics and `read_event` return type

Risk score

Why this scored 48/100

Our methodology →
Potential impact 12/30
Exploitability 8/25
Stealth signal 7/15
Affected reach 10/15
Confidence 7/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.