Skip to content

[Linux] Periodic stutter caused by GamepadUpdate enumerating HID devices every callback #500

@MagiusCHE

Description

@MagiusCHE

Describe the bug

On Linux, GamepadUpdate in libsteam_api.so causes periodic main-thread stalls of 50–200 ms every 2–3 seconds when the host has many HID devices connected (gaming keyboards/mice with multiple endpoints, wireless USB dongles). The stalls come from many slow close() syscalls on input device file descriptors performed during a single SteamAPI_RunCallbacks() invocation.

strace -k shows the close syscalls taking 10–23 ms each (instead of microseconds), all originating from the same call stack:

__close (libc.so.6)
libsteam_api.so [+0x152947]
libsteam_api.so GamepadUpdate+0x127
libsteam_api.so [+0x1280e6]
libsteam_api.so [+0x1f568f]

A single RunCallbacks triggers tens of these closes; the cumulative time blocks the game's main thread for ~100–300 ms, visible as stutter. The same game running through legitimate Steam on the same host shows no stutter at all.

Workaround that fixes it: disable SteamInput AND remove the steam_settings/controller/ folder (the emu auto-enables SteamInput when action sets are present, ignoring steam_input=0 alone):

# steam_settings/configs.app.ini
[app::controller]
steam_input=0
mv steam_settings/controller steam_settings/controller.disabled

Suggested fix: cache HID/input device file descriptors inside GamepadUpdate instead of reopening/closing them on every callback tick. Use udev/inotify on /dev/input to trigger re-enumeration only on hotplug events.

Emulator version

Tested on builds 2026_03_28 and 2026_04_25 — both affected.

Debug log

debug-log.log

steam_settings file

steam_settings.zip

Infos

  • Game: Slay the Spire 2 (Godot 4.5 + .NET; calls SteamAPI_RunCallbacks every frame)
  • SteamAppId: 2868840
  • Denuvo: No

Requirement

  • I am uploaded debug log.
  • I am uploaded steam_setting file.
  • I am sure the game not using 3rd party server (Photon, Playfab, GC, etc).
  • I am sure can run the game offline.

To Reproduce

  1. Use a Linux host with several HID devices connected (one gaming keyboard with media-key endpoints + one gaming mouse + one wireless USB dongle is enough — cat /proc/bus/input/devices should list ~10+ device nodes).
  2. Install Slay the Spire 2 (or any game that calls SteamAPI_RunCallbacks every frame) with gbe_fork.
  3. Make sure steam_settings/controller/ exists with action sets (this is the default for many cracks — it auto-enables SteamInput inside the emu).
  4. Launch the game and stay on the main menu.
  5. Observe ~100 ms freezes recurring every 2–3 seconds.

Expected behavior

Smooth 60 FPS at the main menu with no periodic stalls, matching the behavior of the same game running through legitimate Steam.

Screenshots

N/A — the bug is timing-based and not visible in screenshots.

Additional context

Environment:

  • Manjaro Linux, kernel 6.18.18
  • KDE Plasma 6 on Wayland
  • NVIDIA RTX 4070 Ti, driver 590.48
  • Intel i7-13700K
  • HID: Corsair K70 RGB (3 input nodes), ROCCAT Kone Pure Owl-Eye (5 input nodes), wireless "2.4G Mouse" dongle (3 input nodes)

Already ruled out as causes (issue persists with all of these applied/tested):

  • Different gbe_fork builds (March vs April 2026)
  • Networking flags: disable_networking=1, offline=1, disable_lan_only=1, disable_source_query=1, disable_lobby_creation=1, disable_sharing_stats_with_gameserver=1
  • Stats/overlay flags: paginated_achievements_icons=-1, stat_achievement_progress_functionality=0, upload_achievements_icons_to_gpu=0
  • Running under unshare -rn (no network namespace)
  • Renaming libsentry.linux.release.x86_64.so
  • Running inside Steam Linux Runtime (Sniper) container
  • X11 vs Wayland, OpenGL vs Vulkan
  • NVIDIA env vars: __GL_VRR_ALLOWED=0, __NV_DISABLE_EXPLICIT_SYNC=1, vblank_mode=0
  • taskset -c 0-15 (P-core pinning on hybrid 13700K)
  • Fresh user profile (clean HOME)
  • Cleared shader and Vulkan pipeline caches

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions