8000 Change gamepad state logic to fix crash by deluca-4139 · Pull Request #445 · univrsal/input-overlay · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Change gamepad state logic to fix crash #445

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

Merged
merged 1 commit into from
Mar 24, 2025

Conversation

deluca-4139
Copy link
Contributor

Summary

This change fixes #426 by moving the gamepad state change logic into the constructor, which ensures it will not be updated until the object is finished being constructed, and therefore not be attempted to be accessed until it is initialized.

Context

Sometime late last year, I started getting a bug where OBS would crash on boot if not in safe mode. My OBS and input-display were both up to date, OBS would run normally without input-display active (or in safe mode), and I had no other plugins installed, so I knew the issue must be with input-display. In addition, the issue persisted across platforms (Flatpak, as well as Portage; and it seems like the issue is also present on Windows, as the linked issue shows). I did some digging and found the above-linked issue, which had the exact same error, log, callstack/backtrace, and also a workaround (unplugging the controller before booting OBS).

When troubleshooting, this is the full backtrace I got with debugging symbols:

Thread 22 "libobs: graphic" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fff8741f6c0 (LWP 11040)]
0x00007ffff32bc274 in pthread_mutex_lock () from /usr/lib64/libc.so.6
(gdb) bt
#0  0x00007ffff32bc274 in pthread_mutex_lock () at /usr/lib64/libc.so.6
#1  0x00007fff8437bbec in __gthread_mutex_lock (__mutex=0x0) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/x86_64-pc-linux-gnu/bits/gthr-default.h:762
#2  std::mutex::lock (this=0x0) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/std_mutex.h:113
#3  std::lock_guard<std::mutex>::lock_guard (this=<synthetic pointer>, __m=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/std_mutex.h:250
#4  gamepad_hook::gamepads::get_controller_from_index (this=0x0, index=<optimized out>) at /home/rose/.config/obs-studio/plugins/input-overlay/src/sources/../hook/gamepad_hook_helper.hpp:138
#5  sources::input_source::update (this=0x55555732a980, settings=0x555557c7bc00) at /home/rose/.config/obs-studio/plugins/input-overlay/src/sources/input_source.cpp:67
#6  0x00007ffff6b6533f in obs_source_deferred_update (source=0x55555782f840) at /usr/src/debug/media-video/obs-studio-31.0.2/obs-studio-31.0.2/libobs/obs-source.c:916
#7  obs_source_video_tick (source=source@entry=0x55555782f840, seconds=seconds@entry=0.0166666657) at /usr/src/debug/media-video/obs-studio-31.0.2/obs-studio-31.0.2/libobs/obs-source.c:1230
#8  0x00007ffff6b6f423 in tick_sources (cur_time=43756480759942, last_time=<optimized out>) at /usr/src/debug/media-video/obs-studio-31.0.2/obs-studio-31.0.2/libobs/obs-video.c:81
#9  obs_graphics_thread_loop (context=context@entry=0x7fff8741e9c0) at /usr/src/debug/media-video/obs-studio-31.0.2/obs-studio-31.0.2/libobs/obs-video.c:1112
#10 0x00007ffff6b71778 in obs_graphics_thread (param=<optimized out>) at /usr/src/debug/media-video/obs-studio-31.0.2/obs-studio-31.0.2/libobs/obs-video.c:1193
#11 0x00007ffff32b8f69 in ??? () at /usr/lib64/libc.so.6
#12 0x00007ffff332b34c in ??? () at /usr/lib64/libc.so.6

The problem lies in #5:

// src/sources/input_source.cpp:67
if (m_settings.use_local_input() && gamepad_hook::state) {
    m_settings.gamepad = gamepad_hook::local_gamepads->get_controller_from_index(m_settings.gamepad_index);

What ends up happening is local_gamepads::get_controller_from_index is getting called on a gamepad that has not been initialized, which crashes because of something regarding the SDL2 init function that gets run.

Fix

The issue can be fixed one of two ways:

  1. Swapping the order of the initialization of SDL and the initialization of the gamepads so that the SDL init doesn't fail:
// src/hook/gamepad_hook_helper.cpp:82
if (!WIN32) {
    local_gamepads = new gamepads;
    sdl_init();
}

The problem with this solution is that it must be mirrored across platforms, which feels like it could run into some issues since the code already exhibits unique behavior for each platform and comments describe inconsistencies.
2. Moving the state change into the constructor, rather than in start()
This I think is the better solution, as it ensures that the state is not changed until the object has been fully initialized, making the state atomic more properly act as the gate which stops any calls to uninitialized objects.

I've also added an additional check where the error from #5 comes from:

// src/sources/input_source.cpp:67
if (m_settings.use_local_input() && gamepad_hook::state && gamepad_hook::local_gamepads) {
    m_settings.gamepad = gamepad_hook::local_gamepads->get_controller_from_index(m_settings.gamepad_index);

This is entirely redundant, but makes me feel a bit better since it confirms that this if statement won't do anything wonky from where it might be called elsewhere.

Extras

I haven't tested this on Windows yet, but the fix works properly on my Gentoo machine. I expect that the logic will also work on other platforms, since I haven't changed anything about the order of operations regarding the other init functions that run, so they should be still functional.

Moves the state change logic into the constructor to ensure that it will not be changed until the object is finished being constructed, as well as adding an additional check in the if statement that requires it to be constructed so that we don't call methods on an uninitialized object.
@univrsal
Copy link
Owner

thanks for the pr

@univrsal univrsal merged commit 0801af3 into univrsal:master Mar 24, 2025
3 checks passed
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 this pull request may close these issues.

OBS Crashes if Controller is connected before startup
2 participants
0