Skip to content

[bug] Release the pipeline lock before mgmt UART writes - #1206

Merged
iximeow merged 5 commits into
masterfrom
zl/softnpu-mgmt-deadlock
Oct 3, 2026
Merged

iximeow merged 5 commits into
masterfrom
zl/softnpu-mgmt-deadlock

Conversation

@zeeshanlakhani

@zeeshanlakhani zeeshanlakhani commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

This bug came up during a long-running voxel session that was constantly dumping table state (in my voxel watcher script). I was able to reproduce this within minutes while running a scadm polling loop.

In the softnpu code, we were yielding a thread while also holding onto a mutex over the entire set of management UART writes. As is, this could lead to a deadlock situation in the guest if a vCPU handling a virtio queue notify blocks on the same pipeline mutex. In this case, the management thread spinning and waiting for FIFO space, with the mutex still being held, could keep the vCPU blocked, unable to return to the guest. If the guest needs this vCPU to drain the UART, then nothing will drain it.

This fix scopes the lock to the table updates and dump capture specifically, serializing and writing the owned snapshot only after the mutex is released.

`handle_management_message` locked the P4 pipeline before dispatching
the request. For dump and radix requests, for example, it kept that lock
while waiting for the guest to drain the 1-byte UART FIFO.

In turn, if a queue notify message could send a vCPU into the
`process_guest_packet` fn, where it waited on the same lock,
that vCPU would not finish its PIO exit. This would lead to the guest
not draining the UART, and, boom, deadlock.

## The Fix

Now, the dump path copies table state while under the lock and writes it
after unlocking happens. Table updates still hold the lock while
changing the pipeline. UART writes now have a deadline, where if a
response times out partway through, the handler will try to write the
missing newline while waiting for the next request.

*Note*: I ran into this issue on a long-running voxel session. The
pre-fix binary reproduces it within minutes under a scadm polling
loop, while the fixed one does not (A/B testing).
@zeeshanlakhani
zeeshanlakhani force-pushed the zl/softnpu-mgmt-deadlock branch from b875003 to c12da84 Compare September 5, 2026 15:31
Comment thread lib/propolis/src/hw/virtio/p9fs.rs
@zeeshanlakhani
zeeshanlakhani force-pushed the zl/softnpu-mgmt-deadlock branch from c12da84 to fb8e165 Compare September 5, 2026 15:32

@iximeow iximeow left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is the change you'd want to make, but fundamentally I don't want to be (further) in the way of changes you need for softnpu or dev work etc.

I will admit upfront that the first time I looked at this change was before you'd edited the PR description to be not what is (afaict) an LLM's description of the problem. I think about LLMs as writers not infrequently. here, I'm also laughing a little because having Claude look at this diff, it said most of the same things I did but in several paragraphs more words. it's hard to convince myself to want to pick up the context around a bug, even if it's very clearly wrong to hold a mutex over a sched_yield(), when my impression is that this code is relegated to /goal make it work.

if this fixes a problem for you, go ahead I guess? I can easily +1 this I suppose. if I should read this as "there is a bug in softnpu.rs, fix plz", then that's also fine and I'd mostly just take out the resyncing idea. either way we go is fine here? but either way I should have made the time to read the context and at least get some review to you sooner.

Comment thread lib/propolis/src/hw/virtio/softnpu.rs Outdated
Comment thread lib/propolis/src/hw/virtio/softnpu.rs Outdated
Comment thread lib/propolis/src/hw/virtio/softnpu.rs Outdated
Comment thread lib/propolis/src/hw/virtio/softnpu.rs Outdated
// scheduled again.
std::thread::yield_now();
}
if write_management_response(&uart, &buf, needs_resync, &log) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is all basically hand-driven dev environment stuff so this doesn't matter: does scadm have an expected semantic of the relationship between the loaded program and the table state it's reading here? if yes: dropping the lock does mean you can have situations like "started reading the table, loaded a new program, finished reading the table, interpreted the table w.r.t the wrong program since it changed out from under you".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote out a TODO here that we can come back to in the DumpRequest case.

Comment thread lib/propolis/src/hw/virtio/softnpu.rs Outdated
@zeeshanlakhani

Copy link
Copy Markdown
Contributor Author

@iximeow I'm going to simplify this change, based on our discussion, and just avoid the lock over the entire mgmt UART write(s). So, I'll remove all the deadlining, resyncing, etc.

@zeeshanlakhani zeeshanlakhani changed the title [bug] Avoid holding the pipeline lock across management uart writes [bug] Release the pipeline lock before mgmt UART writes Oct 3, 2026
The deadlock fix in place already releases the pipeline mutex
before serializing and dumping out entries from all tables. A vCPU
in the virtio queue notify path can then return to the guest and
drain the UART.

After discussion with @iximeow, this simplifies the goal here:
we were yielding a thread while holding a mutex over the entire UART
set of management writes, which is bad. This effort removes
the deadlines and resync handling, restoring the yielding
write loops we had in place. The lock stays scoped to just
the table updates and dump capture.
@zeeshanlakhani
zeeshanlakhani force-pushed the zl/softnpu-mgmt-deadlock branch from 0242d40 to 11cf098 Compare October 3, 2026 04:50
@zeeshanlakhani
zeeshanlakhani requested a review from iximeow October 3, 2026 05:12
@zeeshanlakhani

Copy link
Copy Markdown
Contributor Author

@iximeow updated with the more focused fix.

zeeshanlakhani added a commit that referenced this pull request Oct 3, 2026

@iximeow iximeow left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rad, thank you!

@iximeow
iximeow merged commit 7784892 into master Oct 3, 2026
14 checks passed
@iximeow
iximeow deleted the zl/softnpu-mgmt-deadlock branch October 3, 2026 15:31
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.

2 participants