Event ordering & node.dont-reconnect handling
Preamble: I've been looking into why Zoom desktop audio sharing doesn't work on Wireplumber; after pipewire!1150 (merged) it works on pipewire-media-session, and the problem on Wireplumber seems to be node.dont-reconnect handling.
What's going on: the app in Pulse API creates null sink (with name, say, record
), then combine-sink (combine
) with "record" as target, and then a recording stream (loopback
) with node.target
set to "combine". All the streams are with node.dont-reconnect
being true.
After loading each sink, pipewire-pulse waits (with pipewire!1150 (merged)) that the nodes get bound to an id on the server, before returning (and the app waits for that). So the three steps are done one after the other, and pipewire-pulse controls when to move to the next one, but they occur rapidly.
The app hangs when Wireplumber handles these events out of the intended order, and ends up destroying the dont-reconnect nodes (which is what policy-node.lua does in some cases). Or at least that's my current understanding.
This fixes it (iirc p-m-s does it a bit like this), but I don't really like it: https://gitlab.freedesktop.org/pvir/wireplumber/-/tree/fix-reconnect-debug-20220214
It maybe connected, but it seems that the order of registry_global events, and the order in which linkables appear in linkables_om is not the same. E.g. in the logs with the fix-reconnect-debug branch I see
D 00:07:23.966916 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001010> global:114 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:zoomrecord)
D 00:07:23.967035 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001210> global:114 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:zoomrecord)
...
D 00:07:23.989903 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001010> global:102 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:zoomcombine)
D 00:07:23.990288 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001210> global:102 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:zoomcombine)
...
D 00:07:24.000190 script/policy-node policy-node.lua:778:chunk: <WpSiAudioAdapter:0x6250014ecb80> add node zoomrecord
...
D 00:07:24.012723 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001010> global:110 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:ZOOM VoiceEngine Loopback)
D 00:07:24.013243 wp-registry ../lib/wp/object-manager.c:912:registry_global: <WpCore:0x625000001210> global:110 perm:0x1c8 type:PipeWire:Interface:Node/3 -> WpNode (node.name:ZOOM VoiceEngine Loopback)
...
D 00:07:24.046727 script/policy-node policy-node.lua:778:chunk: <WpSiAudioAdapter:0x6250014ec220> add node ZOOM VoiceEngine Loopback
I 00:07:24.046912 script/policy-node policy-node.lua:550:handleLinkable: <WpSiAudioAdapter:0x6250014ec220> handling item: ZOOM VoiceEngine Loopback (110)
D 00:07:24.047010 script/policy-node policy-node.lua:274:findDefinedTarget: ... defined target: zoomcombine
I 00:07:24.048105 script/policy-node policy-node.lua:579:handleLinkable: <WpSiAudioAdapter:0x6250014ec220> ... waiting for target (1/5)
...
D 00:07:24.068348 script/policy-node policy-node.lua:778:chunk: <WpSiAudioAdapter:0x6250014ec9a0> add node zoomcombine
I.e. ordering of nodes appearing differs; maybe for good reason in case it waits for properties etc., and this may be a red herring since iiuc nodes may not be immediately linkable. However, in current Wireplumber master, policy-node under some cases ends up in the branch with node:request_destroy() in handleLinkable.
So the question is: how should this work? How do the client and session manager organize it so that nodes created in "right" sequence from the point of view of the client get connected correctly? Should the dont-reconnect handling in wireplumber be changed? Or should pipewire-pulse wait for some other event before returning, and allowing the app to go to the next step?