Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Carla lists and draw "empty" connections #1625

Open
EvTheFuture opened this issue May 30, 2022 · 16 comments · May be fixed by #1748
Open

Carla lists and draw "empty" connections #1625

EvTheFuture opened this issue May 30, 2022 · 16 comments · May be fixed by #1748

Comments

@EvTheFuture
Copy link
Contributor

Carla "sees" connections that is not there and draw them...

image

Distribution: Alpine 3.16
Pipewire: master

Output of pw-link -l

masa@gurkhost (3:503) [~]$ pw-link -l
Processed Microphones:capture_FL
  |-> Mixed Sources:input_FL
  |-> Analyzer - Processed Microphones:Input 0
  |-> Google Chrome input:input_FL
Processed Microphones:capture_FR
  |-> Mixed Sources:input_FR
  |-> Analyzer - Processed Microphones:Input 1
  |-> Google Chrome input:input_FR
Processed Microphones:input_FL
  |<- Mic EQ10Q Stereo:Output1
Processed Microphones:input_FR
  |<- Mic EQ10Q Stereo:Output2
Mixed Sources:capture_FL
  |-> Recordings:input_FL
Mixed Sources:capture_FR
  |-> Recordings:input_FR
Mixed Sources:input_FL
  |<- Processed Microphones:capture_FL
  |<- Media Sink:capture_FL
Mixed Sources:input_FR
  |<- Processed Microphones:capture_FR
  |<- Media Sink:capture_FR
Recordings:capture_FL
  |-> Analyzer - Recordings:Input 0
Recordings:capture_FR
  |-> Analyzer - Recordings:Input 1
Recordings:input_FL
  |<- Meetings Proc Output:Out Left
  |<- Mixed Sources:capture_FL
  |<- All Outputs:capture_FL
Recordings:input_FR
  |<- Meetings Proc Output:Out Right
  |<- Mixed Sources:capture_FR
  |<- All Outputs:capture_FR
All Outputs:capture_FL
  |-> Recordings:input_FL
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FL
  |-> Analyzer - All Outputs:Input 0
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
All Outputs:capture_FR
  |-> Recordings:input_FR
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FR
  |-> Analyzer - All Outputs:Input 1
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
All Outputs:playback_FL
  |<- Notifications Sink:capture_FL
All Outputs:playback_FR
  |<- Notifications Sink:capture_FR
Media Sink:capture_FL
  |-> Mixed Sources:input_FL
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FL
  |-> Analyzer - Media:Input 0
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
Media Sink:capture_FR
  |-> Mixed Sources:input_FR
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FR
  |-> Analyzer - Media:Input 1
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
Media Sink:playback_FL
  |<- Compressor Sink - Compressor:Out Left
  |<- spotify:output_FL
Media Sink:playback_FR
  |<- Compressor Sink - Compressor:Out Right
  |<- spotify:output_FR
Notifications Sink:capture_FL
  |-> All Outputs:playback_FL
Notifications Sink:capture_FR
  |-> All Outputs:playback_FR
Meetings Sink:capture_FL
  |-> Meetings Proc Input:In Left
Meetings Sink:capture_FR
  |-> Meetings Proc Input:In Right
Meetings Sink:playback_FL
  |<- Google Chrome:output_FL
  |<- Google Chrome:output_FL
  |<- Google Chrome:output_FL
Meetings Sink:playback_FR
  |<- Google Chrome:output_FR
  |<- Google Chrome:output_FR
  |<- Google Chrome:output_FR
Compressor Sink:capture_FL
  |-> Compressor Sink - Compressor:In Left
Compressor Sink:capture_FR
  |-> Compressor Sink - Compressor:In Right
alsa_output.pci-0000_07_00.6.analog-stereo:playback_FL
  |<- Meetings Proc Output:Out Left
  |<- All Outputs:capture_FL
  |<- Media Sink:capture_FL
alsa_output.pci-0000_07_00.6.analog-stereo:playback_FR
  |<- Meetings Proc Output:Out Right
  |<- All Outputs:capture_FR
  |<- Media Sink:capture_FR
alsa_input.pci-0000_07_00.6.analog-stereo:capture_FL
  |-> Mic Noise Reduction:Input (L)
alsa_input.pci-0000_07_00.6.analog-stereo:capture_FR
  |-> Mic Noise Reduction:Input (R)
Meetings Proc Input:Out Left
  |-> Noise Suppressor for Voice (Stereo):Input (L)
Meetings Proc Input:Out Right
  |-> Noise Suppressor for Voice (Stereo):Input (R)
Meetings Proc Input:In Left
  |<- Meetings Sink:capture_FL
Meetings Proc Input:In Right
  |<- Meetings Sink:capture_FR
Meetings Proc Output:Out Left
  |-> Recordings:input_FL
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FL
  |-> Analyzer - All Outputs:Input 0
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
Meetings Proc Output:Out Right
  |-> Recordings:input_FR
  |-> alsa_output.pci-0000_07_00.6.analog-stereo:playback_FR
  |-> Analyzer - All Outputs:Input 1
  |-> bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
Meetings Proc Output:In Left
  |<- Noise Suppressor for Voice (Stereo):Output (L)
Meetings Proc Output:In Right
  |<- Noise Suppressor for Voice (Stereo):Output (R)
Analyzer - All Outputs:Input 0
  |<- Meetings Proc Output:Out Left
  |<- All Outputs:capture_FL
Analyzer - All Outputs:Input 1
  |<- Meetings Proc Output:Out Right
  |<- All Outputs:capture_FR
Analyzer - Media:Input 0
  |<- Media Sink:capture_FL
Analyzer - Media:Input 1
  |<- Media Sink:capture_FR
Analyzer - Processed Microphones:Input 0
  |<- Processed Microphones:capture_FL
Analyzer - Processed Microphones:Input 1
  |<- Processed Microphones:capture_FR
Compressor Sink - Compressor:Out Left
  |-> Media Sink:playback_FL
Compressor Sink - Compressor:Out Right
  |-> Media Sink:playback_FR
Compressor Sink - Compressor:In Left
  |<- Compressor Sink:capture_FL
Compressor Sink - Compressor:In Right
  |<- Compressor Sink:capture_FR
Mic delay:Out
  |-> Mic Noise Reduction:Input (L)
Mic delay:In
  |<- bluez_input.4C_87_5D_27_8D_17.headset-head-unit:capture_MONO
Mic EQ10Q Stereo:Output1
  |-> Processed Microphones:input_FL
Mic EQ10Q Stereo:Output2
  |-> Processed Microphones:input_FR
Mic EQ10Q Stereo:Input1
  |<- LSP Compressor Stereo:Output L
Mic EQ10Q Stereo:Input2
  |<- LSP Compressor Stereo:Output R
LSP Compressor Stereo:Output L
  |-> Mic EQ10Q Stereo:Input1
LSP Compressor Stereo:Output R
  |-> Mic EQ10Q Stereo:Input2
LSP Compressor Stereo:Input L
  |<- Mic Noise Reduction:Output (L)
LSP Compressor Stereo:Input R
  |<- Mic Noise Reduction:Output (R)
Mic Noise Reduction:Output (L)
  |-> LSP Compressor Stereo:Input L
Mic Noise Reduction:Output (R)
  |-> LSP Compressor Stereo:Input R
Mic Noise Reduction:Input (L)
  |<- alsa_input.pci-0000_07_00.6.analog-stereo:capture_FL
  |<- Mic delay:Out
Mic Noise Reduction:Input (R)
  |<- alsa_input.pci-0000_07_00.6.analog-stereo:capture_FR
  |<- bluez_input.4C_87_5D_27_8D_17.headset-head-unit:capture_MONO
Noise Suppressor for Voice (Stereo):Output (L)
  |-> Meetings Proc Output:In Left
Noise Suppressor for Voice (Stereo):Output (R)
  |-> Meetings Proc Output:In Right
Noise Suppressor for Voice (Stereo):Input (L)
  |<- Meetings Proc Input:Out Left
Noise Suppressor for Voice (Stereo):Input (R)
  |<- Meetings Proc Input:Out Right
Analyzer - Recordings:Input 0
  |<- Recordings:capture_FL
Analyzer - Recordings:Input 1
  |<- Recordings:capture_FR
spotify:output_FL
  |-> Media Sink:playback_FL
spotify:output_FR
  |-> Media Sink:playback_FR
bluez_input.4C_87_5D_27_8D_17.headset-head-unit:capture_MONO
  |-> Mic delay:In
  |-> Mic Noise Reduction:Input (R)
bluez_output.4C_87_5D_27_8D_17.headset-head-unit:playback_MONO
  |<- All Outputs:capture_FL
  |<- All Outputs:capture_FR
  |<- Media Sink:capture_FL
  |<- Media Sink:capture_FR
  |<- Meetings Proc Output:Out Left
  |<- Meetings Proc Output:Out Right
Google Chrome:output_FL
  |-> Meetings Sink:playback_FL
Google Chrome:output_FR
  |-> Meetings Sink:playback_FR
Google Chrome:output_FL
  |-> Meetings Sink:playback_FL
Google Chrome:output_FR
  |-> Meetings Sink:playback_FR
Google Chrome:output_FL
  |-> Meetings Sink:playback_FL
Google Chrome:output_FR
  |-> Meetings Sink:playback_FR
Google Chrome input:input_FL
  |<- Processed Microphones:capture_FL
Google Chrome input:input_FR
  |<- Processed Microphones:capture_FR

I guess i would be possible to just skip drawing/listing "empty" peers?
But I guess the more important question might be why it happen in the first place...

@falkTX
Copy link
Owner

falkTX commented May 30, 2022

I never see this using real jack, and unless you see that using jack as well, this is pretty much a "wont fix".
blame pipewire for now behaving like real jack, as it is supposed to.

@EvTheFuture
Copy link
Contributor Author

Would you reject a PR that implement ignore of these?

@falkTX
Copy link
Owner

falkTX commented May 30, 2022

Not really, but a warning would need to be printed/shown somehow.

@EvTheFuture
Copy link
Contributor Author

This is the output from Carla after one day of usage, don't know if all of these "errors" are caused by the jack implementation:

masa@gurkhost (3:505) [~]$ taskset 0x01 carla ./carla.carxp
Carla 2.4.3 started, status:
  Python version: 3.10.4
  Qt version:     5.15.3
  PyQt version:   5.15.6
  Binary dir:     /usr/lib/carla
  Resources dir:  /usr/share/carla/resources
Frontend pixel ratio is 1.0
libjack.so.0 loaded successfully!
[carla] Will use UI-Bridge for 'Meetings Proc Input', binary: "/usr/lib/carla/carla-bridge-lv2-x11"
[carla] Will use UI-Bridge for 'Meetings Proc Output', binary: "/usr/lib/carla/carla-bridge-lv2-x11"
[carla] Will use LV2 X11 UI for 'Analyzer - All Outputs'
[carla] Will use LV2 X11 UI for 'Analyzer - Media'
[carla] Will use LV2 X11 UI for 'Analyzer - Processed Microphones'
[carla] Will use UI-Bridge for 'Compressor Sink - Compressor', binary: "/usr/lib/carla/carla-bridge-lv2-x11"
[carla] Will use UI-Bridge for 'Mic EQ10Q Stereo', binary: "/usr/lib/carla/carla-bridge-lv2-gtk2"
[carla] Will use LV2 X11 UI for 'LSP Compressor Stereo'
[carla] latency changed to 96 samples
[carla] Will use LV2 X11 UI for 'Analyzer - Recordings'
[carla] Previously saved client 'Firefox' not found
PatchCanvas::CanvasGetFullPortName(35, 112) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 125) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 127) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 135) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 137) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 139) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 141) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 143) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 145) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 147) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 149) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 151) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 153) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 157) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 159) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 161) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 163) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 165) - unable to find port
PatchCanvas::CanvasGetFullPortName(35, 112) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 125) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 127) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 135) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 137) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 139) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 141) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 143) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 145) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 147) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 149) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 151) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 153) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 157) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 159) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 161) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 163) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 165) - unable to find port
PatchCanvas::CanvasGetFullPortName(35, 112) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 125) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 127) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 135) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 137) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 139) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 141) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 143) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 145) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 147) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 149) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 151) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 153) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 157) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 159) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 161) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 163) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 165) - unable to find port
PatchCanvas::CanvasGetFullPortName(35, 113) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 126) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 128) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 136) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 138) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 140) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 142) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 144) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 146) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 148) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 150) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 152) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 154) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 158) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 160) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 162) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 164) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 166) - unable to find port
PatchCanvas::CanvasGetFullPortName(59, 168) - unable to find port
PatchCanvas::CanvasGetFullPortName(60, 170) - unable to find port
PatchCanvas::CanvasGetFullPortName(61, 172) - unable to find port
PatchCanvas::CanvasGetFullPortName(62, 174) - unable to find port
PatchCanvas::CanvasGetFullPortName(35, 113) - unable to find port
PatchCanvas::CanvasGetFullPortName(39, 122) - unable to find port
PatchCanvas::CanvasGetFullPortName(40, 124) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 126) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 128) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 136) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 138) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 140) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 142) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 144) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 146) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 148) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 150) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 152) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 154) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 158) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 160) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 162) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 164) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 166) - unable to find port
PatchCanvas::CanvasGetFullPortName(59, 168) - unable to find port
PatchCanvas::CanvasGetFullPortName(60, 170) - unable to find port
PatchCanvas::CanvasGetFullPortName(61, 172) - unable to find port
PatchCanvas::CanvasGetFullPortName(62, 174) - unable to find port
PatchCanvas::CanvasGetFullPortName(63, 176) - unable to find port
PatchCanvas::CanvasGetFullPortName(64, 178) - unable to find port
PatchCanvas::CanvasGetFullPortName(65, 180) - unable to find port
PatchCanvas::CanvasGetFullPortName(66, 182) - unable to find port
PatchCanvas::CanvasGetFullPortName(67, 184) - unable to find port
PatchCanvas::CanvasGetFullPortName(68, 186) - unable to find port
PatchCanvas::CanvasGetFullPortName(69, 188) - unable to find port
PatchCanvas::CanvasGetFullPortName(70, 190) - unable to find port
PatchCanvas::CanvasGetFullPortName(71, 192) - unable to find port
PatchCanvas::CanvasGetFullPortName(75, 200) - unable to find port
PatchCanvas::CanvasGetFullPortName(77, 206) - unable to find port
PatchCanvas::CanvasGetFullPortName(79, 210) - unable to find port
PatchCanvas::CanvasGetFullPortName(82, 216) - unable to find port
PatchCanvas::CanvasGetFullPortName(85, 224) - unable to find port
PatchCanvas::CanvasGetFullPortName(87, 230) - unable to find port
PatchCanvas::CanvasGetFullPortName(88, 232) - unable to find port
PatchCanvas::CanvasGetFullPortName(90, 236) - unable to find port
[carla] Carla assertion failure: "fullPortNameA != nullptr && fullPortNameA[0] != '\0'" in file CarlaEngineJack.cpp, line 2391
Disconnect failed: Invalid or unsupported plugin type
PatchCanvas::CanvasGetFullPortName(35, 113) - unable to find port
PatchCanvas::CanvasGetFullPortName(39, 122) - unable to find port
PatchCanvas::CanvasGetFullPortName(40, 124) - unable to find port
PatchCanvas::CanvasGetFullPortName(41, 126) - unable to find port
PatchCanvas::CanvasGetFullPortName(42, 128) - unable to find port
PatchCanvas::CanvasGetFullPortName(45, 136) - unable to find port
PatchCanvas::CanvasGetFullPortName(46, 138) - unable to find port
PatchCanvas::CanvasGetFullPortName(47, 140) - unable to find port
PatchCanvas::CanvasGetFullPortName(48, 142) - unable to find port
PatchCanvas::CanvasGetFullPortName(49, 144) - unable to find port
PatchCanvas::CanvasGetFullPortName(50, 146) - unable to find port
PatchCanvas::CanvasGetFullPortName(51, 148) - unable to find port
PatchCanvas::CanvasGetFullPortName(52, 150) - unable to find port
PatchCanvas::CanvasGetFullPortName(53, 152) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 154) - unable to find port
PatchCanvas::CanvasGetFullPortName(54, 158) - unable to find port
PatchCanvas::CanvasGetFullPortName(55, 160) - unable to find port
PatchCanvas::CanvasGetFullPortName(56, 162) - unable to find port
PatchCanvas::CanvasGetFullPortName(57, 164) - unable to find port
PatchCanvas::CanvasGetFullPortName(58, 166) - unable to find port
PatchCanvas::CanvasGetFullPortName(59, 168) - unable to find port
PatchCanvas::CanvasGetFullPortName(60, 170) - unable to find port
PatchCanvas::CanvasGetFullPortName(61, 172) - unable to find port
PatchCanvas::CanvasGetFullPortName(62, 174) - unable to find port
PatchCanvas::CanvasGetFullPortName(63, 176) - unable to find port
PatchCanvas::CanvasGetFullPortName(64, 178) - unable to find port
PatchCanvas::CanvasGetFullPortName(65, 180) - unable to find port
PatchCanvas::CanvasGetFullPortName(66, 182) - unable to find port
PatchCanvas::CanvasGetFullPortName(67, 184) - unable to find port
PatchCanvas::CanvasGetFullPortName(68, 186) - unable to find port
PatchCanvas::CanvasGetFullPortName(69, 188) - unable to find port
PatchCanvas::CanvasGetFullPortName(70, 190) - unable to find port
PatchCanvas::CanvasGetFullPortName(71, 192) - unable to find port
PatchCanvas::CanvasGetFullPortName(75, 200) - unable to find port
PatchCanvas::CanvasGetFullPortName(77, 206) - unable to find port
PatchCanvas::CanvasGetFullPortName(79, 210) - unable to find port
PatchCanvas::CanvasGetFullPortName(82, 216) - unable to find port
PatchCanvas::CanvasGetFullPortName(85, 224) - unable to find port
PatchCanvas::CanvasGetFullPortName(87, 230) - unable to find port
PatchCanvas::CanvasGetFullPortName(88, 232) - unable to find port
PatchCanvas::CanvasGetFullPortName(90, 236) - unable to find port
[carla] Will use UI-Bridge for 'EQ10Q Stereo', binary: "/usr/lib/carla/carla-bridge-lv2-gtk2"
[carla] Will use LV2 X11 UI for 'LSP Limiter Stereo'
qt.qpa.wayland: Wayland does not support QWindow::requestActivate()
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
qt.qpa.wayland: Wayland does not support QWindow::requestActivate()
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
[carla] Carla assertion failure: "fHeapBuffer.buf == nullptr" in file ../../utils/Lv2AtomRingBuffer.hpp, line 77
libgtk-x11-2.0.so.0 loaded successfully!
[carla] ALL OK!

(carla-bridge-lv2-gtk2:11020): Gtk-WARNING **: 08:41:18.601: Unable to locate theme engine in module_path: "adwaita",

(carla-bridge-lv2-gtk2:11020): Gtk-WARNING **: 08:41:18.605: Unable to locate theme engine in module_path: "adwaita",
[INF] Building UI from dynamics/limiter/single/stereo.xml, parent window=0x600001
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
libgtk-x11-2.0.so.0 loaded successfully!
[carla] ALL OK!

(carla-bridge-lv2-gtk2:11425): Gtk-WARNING **: 08:50:57.105: Unable to locate theme engine in module_path: "adwaita",

(carla-bridge-lv2-gtk2:11425): Gtk-WARNING **: 08:50:57.108: Unable to locate theme engine in module_path: "adwaita",
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
[carla] Carla assertion failure: "size > 0" in file CarlaPluginLV2.cpp, line 5854
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
libgtk-x11-2.0.so.0 loaded successfully!
[carla] ALL OK!

(carla-bridge-lv2-gtk2:24870): Gtk-WARNING **: 10:55:53.285: Unable to locate theme engine in module_path: "adwaita",

(carla-bridge-lv2-gtk2:24870): Gtk-WARNING **: 10:55:53.288: Unable to locate theme engine in module_path: "adwaita",
qt.qpa.wayland: Wayland does not support QWindow::requestActivate()
libgtk-x11-2.0.so.0 loaded successfully!
[carla] ALL OK!

(carla-bridge-lv2-gtk2:24905): Gtk-WARNING **: 10:56:39.379: Unable to locate theme engine in module_path: "adwaita",

(carla-bridge-lv2-gtk2:24905): Gtk-WARNING **: 10:56:39.382: Unable to locate theme engine in module_path: "adwaita",
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647
Traceback (most recent call last):
  File "/usr/share/carla/carla_host.py", line 2797, in timerEvent
    self.idleSlow()
  File "/usr/share/carla/carla_host.py", line 2781, in idleSlow
    self.getAndRefreshRuntimeInfo()
  File "/usr/share/carla/carla_host.py", line 2746, in getAndRefreshRuntimeInfo
    self.refreshRuntimeInfo(info['load'], info['xruns'])
  File "/usr/share/carla/carla_host.py", line 2738, in refreshRuntimeInfo
    self.ui.pb_dsp_load.setValue(int(load))
OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647

@mxmilkiib
Copy link
Contributor

If anyone makes an issue in the PW tracker, link to it from here, ta. Hard to tell if chat in #pipewire confirming this issue but stating it is a possible wontfix is personal opinion or truth (though AFAIU PW should always behave like JACK, so maybe they were just being defensive).

@tatokis
Copy link

tatokis commented May 31, 2022

Try running this (being mindful of your ears).
It might also leave some leftover processes that will need to be cleaned up manually.

#!/usr/bin/env bash

while true; do
    jack_simple_client&
    sleep 0.05
    killall jack_simple_client
done

With this I was able to reproduce this on "real jack" in a VM (thus the constant xruns) with the dummy driver.

3a41c1d0110e

@tatokis
Copy link

tatokis commented Jun 11, 2022

To expand on this, the reason I believe this happens is because there is a data race somewhere in Carla, and it's just a matter of chances. If am correct, typical jack usage consists of starting up a few clients and then they remain connected for the remainder of the session.

In contrast, on typical desktop usage with something like pipewire, every single notification sound can be a separate client that connects, plays the sound, and immediately disconnects. And if you have multiple notifications happening at the same time, say from different people, then you get clients connecting and disconnecting in rapid succession.

Another case is when playing a video in Firefox, every seek usually results in the pulse client being destroyed and recreated, which is in turn mirrored over the jack api in pipewire.

I discovered this due to libcanberra making a new client every time the system volume is changed, having to play a "click" sound. I can basically get Carla to misbehave just by changing my system volume (under pipewire).

In addition, the data race can get bad enough that results in Carla segfaulting. It seems to be because invalid data gets passed to Qt for rendering.
That said, I have not reproduced the segfault in the VM with jack, however that might just be because the test script spawns clients in a different pattern, or the VM is slower due to lack of fast graphics acceleration. The hanging wires are 100% reproducible though. After playing with the timing a bit, I got the segfault in the VM with jackd2, too.

In the following video you can observe this happening (under pipewire) and then eventually resulting in a segfault.
https://vps.tasossah.com/carla_race.mp4

So, keeping in consideration this behaviour difference, and the fact that one can reproduce this with the script I shared above in jack itself, I believe this is in fact a bug in Carla, and just because most jack clients don't behave this way doesn't mean it's not a valid use case. If one could get desktop notification sounds over jack in this fashion, or if Firefox behaved the same way under native jack (haven't tried building it with jack support), I believe it'd have been observed much earlier.

It is worth noting that it seems nearly impossible to run Carla with ThreadSanitizer due to Python getting in the way. It's also considerably more difficult to trigger the segfault with gdb attached to Carla, which gives more credibility to the data race theory.

Finally, here's what the backtrace of a segfault looks like (in html to preserve text colouring for readability).
https://vps.tasossah.com/carlasegfault.html

Hope this helps.

@mxmilkiib
Copy link
Contributor

@tatokis Do you see this problem at all with either JACK2 or JACK1 by using the script you created to reproduce it?

@tatokis
Copy link

tatokis commented Jun 11, 2022

@mxmilkiib Yes. You can reproduce it on jack2 with that script.

@EvTheFuture
Copy link
Contributor Author

@mxmilkiib Yes. You can reproduce it on jack2 with that script

Just out of curiosity, can you reproduce it when Carla is pinned to one CPU core with for instance taskset 0x01 Carla <project file>?

Your theory would explain why I see lots of this since I have multiple VMs running, all with a PulseAudio connection to pipewire and some VMs create notifications simultaneously.

@tatokis
Copy link

tatokis commented Jun 13, 2022

@EvTheFuture Yes, it happens when pinned to core 0 too (with jack2).

@ecruz1986
Copy link

ecruz1986 commented Feb 24, 2023

I'm very bothered by this and I've been investigating it.

I'm using pipewire and KDE plasma. I can trigger the bug every time by hovering over the volume icon on the tray and quickly turning the mouse wheel up (or down), causing quick successive volume changes and quick playback of the KDE plasma volume check tone. This playback shows up in jack/Carla as libcanberra.

I have dug into source/frontend/patchcanvas/patchcanvas.py and forced debug=True inside init().
I have captured this piece of log while doing a quick mouse wheel-up roll over the volume tray icon, so it is probably logging two quick subsequent playbacks of the KDE volume test tone.

PatchCanvas::addGroup(7, b'libcanberra', SPLIT_UNDEF, ICON_APPLICATION)
PatchCanvas::CanvasGetNewGroupPos(False)
PatchCanvas::addPort(7, 35, b'output_FL', PORT_MODE_OUTPUT, PORT_TYPE_AUDIO_JACK, False)
PatchCanvas::addPort(7, 36, b'output_FR', PORT_MODE_OUTPUT, PORT_TYPE_AUDIO_JACK, False)
PatchCanvas::connectPorts(1, 7, 35, 4, 5)
PatchCanvas::connectPorts(2, 7, 36, 4, 6)
PatchCanvas::addPort(7, 37, b'output_FL', PORT_MODE_OUTPUT, PORT_TYPE_AUDIO_JACK, False)
PatchCanvas::addPort(7, 38, b'output_FR', PORT_MODE_OUTPUT, PORT_TYPE_AUDIO_JACK, False)
PatchCanvas::connectPorts(3, 7, 35, 4, 5)
PatchCanvas::connectPorts(4, 7, 36, 4, 6)
PatchCanvas::disconnectPorts(1)
PatchCanvas::removePort(7, 35)
PatchCanvas::disconnectPorts(2)
PatchCanvas::removePort(7, 36)
PatchCanvas::removeGroup(7)

First we see that it creates the group libcanberra with ID 7, and a pair of ports on the libcanberra group for FL and FR with IDs 35 and 36 and connects them to my output, generating connections with IDs 1 and 2. So far so good.

But then, as the second playback tone comes, we see that it creates yet another pair of ports on the same group (ports with IDs 37 and 38) but when it comes the time to connect them, it actually connects the old ports 35 and 36 again, creating duplicate connections (same input/output ports!) with IDs 3 and 4.

When it comes the time to clean up everything, it only disconnects the connections 1 and 2 and removes the ports 35 and 36. The connections 3 and 4 never got the disconnectPorts() call, and I assume they become orphaned/zombie connections that can even be seen as the crazy artifact lines on the canvas and will later cause the segfault crash. Also we note that ports 37 and 38 never got the "removePort()" call, so they might be zombieing too.

I think those extra ports (37 and 38) should never have been created at all, I think the old ports should have somehow been reused for the second playback. When doing the same experiment over Helvum, I don't see any extra ports being created on the GUI, libcanberra just stays there with 2 ports even if I spam the mouse wheel over the volume icon. If I do this on Carla, I can momentarily see the libcanberra group with dozens of ports.

I'm not sure if this is pipewire's fault or Carla's fault. I don't have any knowledge in jack implementation, so difficult for me to say. I don't know if I will be able to find out more, but if I can't progress, I hope the information here can help somebody.

@ecruz1986
Copy link

ecruz1986 commented Feb 24, 2023

I've tweaked @tatokis's script a little bit. With this one, I can reproduce it in pipewire (although not 100% of the time, might take a few tries). With this I can observe the bogus intermediate state in Carla while the script pauses.


#!/usr/bin/env bash

# Keep Carla patchbay visible while running this

jack_simple_client &> /dev/null &
# we must kill the newly created client quickly to trigger the bug. If we delay this kill by too much, the bug won't trigger.
killall jack_simple_client
jack_simple_client &> /dev/null &
echo "You should now be able to see jack_simple_client on Carla with duplicate ports and duplicate connection on the first ports."
read -n 1 -s -r -p "Press any key to kill it..."
killall jack_simple_client
echo "Now Carla should be left with connections leading to nowhere."


Here's what I see in Carla during the pause. There are duplicate ports, coherent with the log that I posted on my last message.
image

And the connections on the first two ports are duplicated, also coherent with the log:
image

After the script continues and kills the second jack_simple_client, Carla is left with empty connections:
image

@falkTX
Copy link
Owner

falkTX commented Feb 24, 2023

using canvas menu -> refresh makes the bad connections go away, correct?

@ecruz1986
Copy link

using canvas menu -> refresh makes the bad connections go away, correct?

Yes it does. Even in the duplicated ports state, if I refresh the Canvas (CTRL+R), it will correctly redraw the jack_simple_client group and make it show only 2 ports instead of 4 and without the duplicate connections.

@ecruz1986
Copy link

I found the piece of code that's relevant for this bug and I can explain why it is happening.

In file source/backend/engine/CarlaEngineJack.cpp, in the method run() around line 4202 there is a loop that consumes a queue of postponed jack events.

This loop runs once every 200ms. So if a client's port is created and then destroyed very quickly *(within 200ms), it's possible that we are unlucky and both their kTypePortRegister and kTypePortUnregister events are grouped in the same batch of the loop.

This loop runs in 2 iterations and it doesn't process the events exactly in the order of the queue. kTypePortUnregister are consumed in the first iteration, and kTypePortRegister is consumed later in the second iteration. The code is prepared to remember the port unregister requests in a portsToIgnore list during the first iteration, so it can ignore the registration of the same port later in the second iteration, as if it were never registered.

The code works well if there's only one client involved. However problems arise if we have more than one client+port showing up on the same batch and having the same name, which is the case when a client is killed and started again.

For example, if we do what's done in my script above: run jack_simple_client, kill it, and then run it again (all unluckily done within the 200ms loop window): the second jack_simple_client process will have the same jack client name as the the first, and the batch will contain events for both of these processes, but they will be confused among each other because they have the same client and port name (effectivelly, same ID).

Let's look only at port "output1" of "jack_simple_client". The ev.portRegister.fullName is the same "jack_simple_client:output1" string for both the first and the second run of jack_simple_client.

So the queue will have 3 port events, in this order: kTypePortRegister (1st PID), kTypePortUnregister (1st PID), and kTypePortRegister (2nd PID), all with the string "jack_simple_client:output1".

The first iteration (1st for loop) will first try to remove the string entry from portsToIgnore while processing the kTypePortRegister for the first PID, but nothing with be done since the list is still empty. Then it will add the string to the list when processing kTypePortUnregister for the first PID, only to remove it again from the list when processing the kTypePortRegister for the second PID.
So at the end of the first iteration, portsToIgnore is left without the string "jack_simple_client:output1".

And we reach the second iteration (2nd for loop) still with two kTypePortRegister events on the queue, and with an empty portsToIgnore. This leads to the port being registered twice, and leads to the duplicate output ports on my screenshot on my previous post.

Similar crazy stuff happens with the duplicate connections, they also use the portsToIgnore list mechanism.

So there's the bug... I hope I could make myself understood. I think we can conclude it should indeed be fixed inside Carla and not in pipewire. It is triggered way more often in pipewire because it has the habit of destroying and quickly recreating clients upon quick stop&play operations like the KDE plasma volume tone scenario... But I don't think there's anything inherently wrong with that, I think Carla should be lenient with this behavior, since it can even be reproduced in native jack.

I feel that the issue lies in the removeOne() call over the list being just ignored whenever it is empty. It should actually be remembered as a something of a -1 credit count, so the next append() should effectively be ignored. What should matter is the overall balance of removes and appends attempts over that list, the order in which they are invoked should not matter.

I can try to use a different structure for this "ignore" mechanism, but I would still need to get more familiar with the code since I literally started looking into Carla code yesterday. I'm not comfortable yet to submit a pull request with clean code without the risk of breaking more stuff.

Maybe now it's an easy fix for you @falkTX ?

@ecruz1986 ecruz1986 linked a pull request Feb 26, 2023 that will close this issue
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 a pull request may close this issue.

5 participants