Sunshine icon indicating copy to clipboard operation
Sunshine copied to clipboard

Crash in PulseAudio init on connecting

Open zb140 opened this issue 2 years ago • 11 comments

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

zb140 avatar Jun 26 '22 14:06 zb140

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.

ReenigneArcher avatar Jun 26 '22 14:06 ReenigneArcher

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.

zb140 avatar Jun 26 '22 14:06 zb140

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.

zb140 avatar Jun 26 '22 15:06 zb140

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?

zb140 avatar Jun 26 '22 15:06 zb140

@some_property@ are variables defined at build time by cmake, so no I don't think that is a valid solution.

ReenigneArcher avatar Jun 26 '22 16:06 ReenigneArcher

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.

ReenigneArcher avatar Jun 26 '22 16:06 ReenigneArcher

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.

zb140 avatar Jun 26 '22 16:06 zb140

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.

github-actions[bot] avatar Sep 25 '22 00:09 github-actions[bot]

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.

zb140 avatar Sep 25 '22 02:09 zb140

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.

ReenigneArcher avatar Sep 28 '22 13:09 ReenigneArcher

This issue has been fixed and will be available in the next release.

github-actions[bot] avatar Oct 11 '22 12:10 github-actions[bot]