Skip to content

Discord Presence crashes app #846

Description

@technomooney

good day, i have found that trackma is crashing on me a lot. i figured out that its the discord presence hook thats doing that. it seems its attempting to open too many sockets without closing them before retrying. i figured that out on my own but i used ai to write it up as a nicer looking right up,

presence hook leaks file descriptors, crashes trackma-qt

Been using the presence hook for a while and noticed trackma-qt would crash after running for some time, quicker when Discord wasn't open.

What's happening

Every second, _reconnect() creates a new Client object and calls start() on it. If Discord isn't available it raises an exception (caught), and tries again next second.

When start() fails because Discord isn't running, sock_writer is never set — it stays None. So close() throws AttributeError on sock_writer.close(), which gets swallowed, and loop.close() is never called.

Every Client() instantiation creates a brand new asyncio event loop via pypresence's get_event_loop(). Each of those loops holds internal epoll/pipe file descriptors. Without loop.close() being called, those FDs accumulate every second until the process hits the OS limit (1024 by default on Linux).

Once the limit is hit, socket.socket() throws OSError: [Errno 24] Too many open files. That error isn't in _errors so it propagates uncaught, kills the thread, and then GLib starts failing to create its own pipes which takes down the whole process with SIGTRAP.

Crash log

Traceback (most recent call last):
  File "/usr/lib/python3.14/threading.py", line 1082, in _bootstrap_inner
    self._context.run(self.run)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/home/martym/.config/trackma/hooks/presence.py", line 87, in run
    self._reconnect()
    ~~~~~~~~~~~~~~~^^
  File "/home/martym/.config/trackma/hooks/presence.py", line 123, in _reconnect
    self._rpc.start()
    ~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/pypresence/client.py", line 284, in start
    self.loop.run_until_complete(self.handshake())
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/asyncio/base_events.py", line 719, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/pypresence/baseclient.py", line 145, in handshake
    ipc_path = get_ipc_path(self.pipe)
  File "/usr/lib/python3.14/site-packages/pypresence/utils.py", line 65, in get_ipc_path
    and test_ipc_path(entry.path)
        ~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/pypresence/utils.py", line 28, in test_ipc_path
    with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
         ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/socket.py", line 236, in __init__
    _socket.socket.__init__(self, family, type, proto, fileno)
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 24] Too many open files

(process:3080659): GLib-ERROR **: 21:47:56.746: Creating pipes for GWakeup: Too many open files

fish: Job 1, 'trackma-qt -d &' terminated by signal SIGTRAP (Trace or breakpoint trap)

Fix

Instead of going through _rpc.close() (which fails before reaching loop.close() on a never-connected client), close the loop directly:

def _reconnect(self):
    if not self._enabled:
        try:
            if self._rpc is not None:
                try:
                    if not self._rpc.loop.is_closed():
                        self._rpc.loop.close()
                except Exception:
                    pass
            self._rpc = Client(self._client_id)
            self._rpc.start()
            self._enabled = True
        except self._errors:
            self._enabled = False

Tested by monitoring /proc/<pid>/fd with Discord closed — FD count stays flat and actually decreases slightly as GC runs, instead of climbing to the limit.

Environment

  • trackma-qt v0.10.3
  • Python 3.14
  • pypresence latest
  • Linux (CachyOS)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions