Sunshine
Sunshine copied to clipboard
Crash in PulseAudio init on connecting
Describe the Bug
I'm using Sunshine in the context of Games on Whales. It's been working great for a while using the older, pre-fork Sunshine, but recently I tried to run with version 0.14.0 and I get a segfault as soon as I try to connect with Moonlight. I grabbed this stacktrace with gdb:
Thread 23 "sunshine-dbg" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffa4804640 (LWP 155)]
0x00007ffff5e15f45 in ?? () from /usr/lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff5e15f45 in ?? () from /usr/lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff6135589 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x0000555555fd1513 in platf::pa::server_t::get_default_sink_name[abi:cxx11]()::{lambda(pa_context*, pa_server_info const*)#1}::operator()(pa_context*, pa_server_info const*) const (
__closure=0x7fffceffbf20, ctx=0x7fffb4001530, server_info=0x7fffa4803230) at /sunshine/sunshine/platform/linux/audio.cpp:400
#3 0x0000555555fd5e06 in std::__invoke_impl<void, platf::pa::server_t::get_default_sink_name()::{lambda(pa_context*, pa_server_info const*)#1}&, pa_context*, pa_server_info const*>(std::__invoke_other, platf::pa::server_t::get_default_sink_name()::{lambda(pa_context*, pa_server_info const*)#1}&, pa_context*&&, pa_server_info const*&&) (__f=...)
at /usr/include/c++/10/bits/invoke.h:60
#4 0x0000555555fd5281 in std::__invoke_r<void, platf::pa::server_t::get_default_sink_name()::{lambda(pa_context*, pa_server_info const*)#1}&, pa_context*, pa_server_info const*>(platf::pa::server_t::get_default_sink_name()::{lambda(pa_context*, pa_server_info const*)#1}&, pa_context*&&, pa_server_info const*&&) (__fn=...) at /usr/include/c++/10/bits/invoke.h:110
#5 0x0000555555fd4426 in std::_Function_handler<void (pa_context*, pa_server_info const*), platf::pa::server_t::get_default_sink_name()::{lambda(pa_context*, pa_server_info const*)#1}>::_M_invoke(std::_Any_data const&, pa_context*&&, pa_server_info const*&&) (__functor=..., __args#0=@0x7fffa48031c0: 0x7fffb4001530, __args#1=@0x7fffa48031b8: 0x7fffa4803230)
at /usr/include/c++/10/bits/std_function.h:291
#6 0x0000555555fd4515 in std::function<void (pa_context*, pa_server_info const*)>::operator()(pa_context*, pa_server_info const*) const (this=0x7fffceffbf20, __args#0=0x7fffb4001530,
__args#1=0x7fffa4803230) at /usr/include/c++/10/bits/std_function.h:622
#7 0x0000555555fd336d in platf::pa::cb<pa_server_info*> (ctx=0x7fffb4001530, i=0x7fffa4803230, userdata=0x7fffceffbf20) at /sunshine/sunshine/platform/linux/audio.cpp:135
#8 0x00007ffff6220579 in ?? () from /usr/lib/x86_64-linux-gnu/libpulse.so.0
#9 0x00007ffff1ea6df3 in ?? () from /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
#10 0x00007ffff1ea780f in pa_pdispatch_run () from /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
#11 0x00007ffff6220873 in ?? () from /usr/lib/x86_64-linux-gnu/libpulse.so.0
#12 0x00007ffff1eab8fd in ?? () from /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
#13 0x00007ffff1ead48f in ?? () from /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
#14 0x00007ffff6234603 in pa_mainloop_dispatch () from /usr/lib/x86_64-linux-gnu/libpulse.so.0
#15 0x00007ffff6234c62 in pa_mainloop_iterate () from /usr/lib/x86_64-linux-gnu/libpulse.so.0
#16 0x00007ffff6234d00 in pa_mainloop_run () from /usr/lib/x86_64-linux-gnu/libpulse.so.0
#17 0x0000555555fcfd61 in platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}::operator()(pa_mainloop*) const (__closure=0x7fffb4003a28, loop=0x7fffb4001430)
at /sunshine/sunshine/platform/linux/audio.cpp:232
#18 0x0000555555fd7560 in std::__invoke_impl<void, platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}, pa_mainloop*>(std::__invoke_other, platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}&&, pa_mainloop*&&) (__f=...) at /usr/include/c++/10/bits/invoke.h:60
#19 0x0000555555fd74bb in std::__invoke<platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}, pa_mainloop*>(platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}&&, pa_mainloop*&&) (
__fn=...) at /usr/include/c++/10/bits/invoke.h:95
#20 0x0000555555fd741b in std::thread::_Invoker<std::tuple<platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}, pa_mainloop*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (
this=0x7fffb4003a28) at /usr/include/c++/10/thread:264
#21 0x0000555555fd7376 in std::thread::_Invoker<std::tuple<platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}, pa_mainloop*> >::operator()() (this=0x7fffb4003a28)
at /usr/include/c++/10/thread:271
#22 0x0000555555fd730e in std::thread::_State_impl<std::thread::_Invoker<std::tuple<platf::pa::server_t::init()::{lambda(pa_mainloop*)#2}, pa_mainloop*> > >::_M_run() (
this=0x7fffb4003a20) at /usr/include/c++/10/thread:215
#23 0x00007ffff60c7694 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#24 0x00007ffff7fa1450 in start_thread () from /usr/lib/x86_64-linux-gnu/libpthread.so.0
#25 0x00007ffff5dadd53 in clone () from /usr/lib/x86_64-linux-gnu/libc.so.6
Expected Behavior
No response
Additional Context
My server_info
pointer is apparently non-null but still invalid, because this is the line that's crashing: https://github.com/SunshineStream/Sunshine/blob/70ae7a2fa9b33173eb949c86ec42a96e7b9e8c25/sunshine/platform/linux/audio.cpp#L400. I haven't done any further digging yet.
Sunshine Host Operating System and Version
unRAID 6.10.3 / Docker, Dockerfile based on Ubuntu 21.04
Architecture
64-bit
Sunshine Version
Built from source at 70ae7a2fa9b33173eb949c86ec42a96e7b9e8c25
GPU Type
Nvidia
GPU Model
GeForce GTX 1660 Ti
GPU Driver/Mesa Version
470.129.06
Capture Method (Linux Only)
X11
GOW is not updated to use the updated fork or version yet. Looks to be in process though. https://github.com/games-on-whales/gow/pull/68
You should probably discuss in that repo.
Yes, I know that, I'm helping debug so we can merge that PR. When I try to run, it segfaults. @ABeltramo asked me to file a ticket here, so I did.
I'm slowly remembering how to use GDB...
The issue appears to be that server_info->default_sink_name
is null, so when line 400 tries to assign it to the std::string
, it crashes.
Thread 23 "sunshine-dbg" hit Breakpoint 1, platf::pa::server_t::get_default_sink_name[abi:cxx11]()::{lambda(pa_context*, pa_server_info const*)#1}::operator()(pa_context*, pa_server_info const*) const (__closure=0x7fffceffbf20, ctx=0x7fffb4001530, server_info=0x7fffa4803230) at /sunshine/sunshine/platform/linux/audio.cpp:400 400 /sunshine/sunshine/platform/linux/audio.cpp: No such file or directory. (gdb) p server_info $1 = (const pa_server_info *) 0x7fffa4803230 (gdb) p *server_info $2 = {user_name = 0x7fffa0007c68 "root", host_name = 0x7fffa0007c6e "68f16dfe4dfd", server_version = 0x7fffa0007c5f "13.99.1", server_name = 0x7fffa0007c53 "pulseaudio", sample_spec = { format = PA_SAMPLE_S16LE, rate = 44100, channels = 2 '\002'}, default_sink_name = 0x0, default_source_name = 0x0, cookie = 2678789789, channel_map = {channels = 2 '\002', map = {
PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_MONO <repeats 30 times>}}}
(gdb) p server_info->default_sink_name
$4 = 0x0
(gdb) c
Continuing.
Thread 23 "sunshine-dbg" received signal SIGSEGV, Segmentation fault.
I think the issue boils down to the fact that my PulseAudio server is also containerized (I'm on unRAID which doesn't have any GUI or audio support by default). So, the get_default_sink_name()
function is running at a time when there aren't any sinks, thus there isn't a default.
root@71135667fc58:~# pacmd list-sinks | grep name:
root@71135667fc58:~#
... connect with moonlight ...
root@71135667fc58:~# pacmd list-sinks | grep name:
name: <sink-sunshine-stereo>
name: <sink-sunshine-surround51>
name: <sink-sunshine-surround71>
root@71135667fc58:~#
... disconnect ...
root@71135667fc58:~# pacmd list-sinks | grep name:
root@71135667fc58:~#
I was able to get past the segfault by just adding a null check around line 400. I think this is a reasonable solution since it's expected that I don't have any sinks -- what do you think?
Edit: Just noticed this in the console after disconnecting:
gow-sunshine-1 | [2022:06:26:10:58:01]: Info: CLIENT DISCONNECTED
gow-sunshine-1 | [2022:06:26:10:58:01]: Info: Setting default sink to: [@DEFAULT_SINK@]
gow-sunshine-1 | [2022:06:26:10:58:01]: Error: Couldn't set default-sink [@DEFAULT_SINK@]: Invalid argument
I'm not sure how much of a real problem that represents. Maybe there should be some logic that skips setting the sink after disconnect if it's known to be this invalid sink name?
@some_property@
are variables defined at build time by cmake, so no I don't think that is a valid solution.
Probably need to do some volume maps from your pulseaudio container back to the host, then map that to your gow container.
Perhaps it will require some additional setup in the gow container... Setting of environment variables or something along those lines. I'm a docker noob though, so probably can't offer much guidance.
Hmm, @DEFAULT_SINK@
doesn't seem to be getting replaced on my build.
In any case, I still think it's a good idea to have a null check around https://github.com/SunshineStream/Sunshine/blob/70ae7a2fa9b33173eb949c86ec42a96e7b9e8c25/sunshine/platform/linux/audio.cpp#L400 since the pulseaudio API sometimes returns null for default_sink_name
and std::string foo = (char*) 0x0
will always crash.
This issue is stale because it has been open for 30 days with no activity. Comment or remove the stale label, otherwise this will be closed in 5 days.
Bump.
#372 fixes this, which I expect will be reviewed (and hopefully merged) as soon as someone gets around to it :grin:
I am, of course, always happy to help in any way I can, so please feel free to ask if there's anything I can do.
I expect will be reviewed (and hopefully merged) as soon as someone gets around to it 😁
Had to take a little time off, will try to get to it soon.
This issue has been fixed and will be available in the next release.