Re: [PATCH] ALSA: seq: midi: wait for output buffer space on non-atomic delivery
From: Junjie Cao
Date: Sun Sep 13 2026 - 07:49:21 EST
On Wed, 02 Sep 2026 15:59:18 +0200, Takashi Iwai wrote:
> When it's transferred as a direct delivery, it should
> just fail like the current version.
Direct delivery is the reported case, though: Chromium's
Web MIDI backend encodes SysEx into events of at most 256
bytes and sends each with snd_seq_event_output_direct(),
one write(2) per event, return value unchecked. The
failure is invisible today: event_process_midi()
returns 0 after dump_midi() fails, so write(2) succeeds
and the tail of the SysEx is gone. A writer that did
check would have nothing to wait on either, since poll()
reports the sender's pool, not the destination.
A direct event from a user client arrives in write(2)
context, so the push-back can copy it into the sender's
pool at the moment the destination reports "full"
(snd_seq_event_dup(), non-blocking); from then on it is
a cell like any queued one. A blocking writer then
waits, before its next direct dispatch, until the pool
has room for the whole event. That is the only sleep,
in snd_seq_write(), outside delivery. Kernel clients
have no pool by default, so what they dispatch directly
(virmidi, MIDI thru) keeps the current drop.
> then one (or a few) of them might block while others
> can process fully.
A private copy per blocked destination sidesteps that:
the delivery loop completes as now and the original cell
is freed; only a destination that reported "full" keeps
a copy plus the consumed offset, and later events for it
queue behind the copy. The copies come out of the
sender's pool, so a stuck destination eventually stalls
a blocking sender's other targets, where today it drops
for the stuck one and goes on; a per-connection cap on
parked cells, dropping beyond it as today, bounds that.
snd_seq_subscribers is the natural home for the copies,
with a list on the port's c_dest for events sent to an
explicit address.
On the resume side dump_var_event() already takes an
offset. What is missing is a space-available callback
on rawmidi output for kernel users: runtime->event fires
on input only, and __snd_rawmidi_transmit_ack() would
have to schedule event_work the way the receive path
does.
I'll write this up as an RFC unless you'd rather see a
different shape first.