Skip to content

lib: don't abort when D-Bus send_with_reply leaves a NULL pending call - #575

Open
shawnyeager wants to merge 1 commit into
FeralInteractive:masterfrom
shawnyeager:fix-347-null-pending-call
Open

shawnyeager wants to merge 1 commit into
FeralInteractive:masterfrom
shawnyeager:fix-347-null-pending-call

Conversation

@shawnyeager

Copy link
Copy Markdown

Fixes #347.

make_request called dbus_pending_call_block(call) without checking that send_with_reply actually produced a pending call. libdbus documents that dbus_connection_send_with_reply() can return TRUE while leaving *pending_return NULL when the connection is disconnected, or when the message carries unix fds the transport cannot send. Blocking on that NULL handle aborts:

arguments to dbus_pending_call_block() were incorrect, assertion "pending != NULL" failed

That is the gamescopereaper SIGABRT on process exit when libgamemodeauto is in LD_PRELOAD (gamemoderun gamescope ...). gamescopereaper closes every fd except stdio (CloseAllFds) after the GameMode constructor has already opened the session bus. The destructor then calls UnregisterGame:

  1. The pidfd attempt still looks connected, so send_with_reply creates a real pending call. The write hits the dead fd, libdbus disconnects, and make_request returns -1.
  2. The retry path (use_pidfs = 0) calls make_request again. The connection is now known-disconnected, so send_with_reply leaves call == NULL, and dbus_pending_call_block(NULL) aborts.

Checking only the boolean return is not enough. This change also rejects call == NULL and returns -1.

meson test includes a regression test that closes the session-bus socket without dbus_connection_close() and then calls UnregisterGame. Without the guard it dies with SIGABRT and the assertion above. With the guard it exits 0.

Verified locally:

# without the guard
meson test ... 'client does not abort after the session bus fd is closed'
FAIL  killed by signal 6 SIGABRT

# with the guard
OK    GameMode ERROR: D-Bus error: Could not send D-Bus message

dbus_connection_send_with_reply() can return TRUE with a NULL
DBusPendingCall when the connection is disconnected, or when the
message carries unix fds the transport cannot send. The client then
called dbus_pending_call_block(NULL), which aborts in libdbus.

That is the gamescopereaper SIGABRT on exit when libgamemodeauto is
preloaded: CloseAllFds closes the bus socket, UnregisterGame retries
without pidfds, and the second send hits the NULL pending call.

Return -1 instead of blocking on a NULL call. A meson test closes the
session bus fd and calls UnregisterGame; it aborted without this
change and exits 0 with it.

Fixes FeralInteractive#347

This branch has not been deployed

No deployments
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.

Should check return value of dbus_connection_send_with_reply in lib/client_impl.c

1 participant