Skip to content

fix(socket_mode): shut down current_session_runner in close()#1874

Open
animaartificialis wants to merge 1 commit into
slackapi:mainfrom
animaartificialis:fix/socket-mode-current-session-runner-leak
Open

fix(socket_mode): shut down current_session_runner in close()#1874
animaartificialis wants to merge 1 commit into
slackapi:mainfrom
animaartificialis:fix/socket-mode-current-session-runner-leak

Conversation

@animaartificialis
Copy link
Copy Markdown

Summary

SocketModeClient starts three IntervalRunner threads in __init__: current_session_runner (0.1 s loop), current_app_monitor (5 s) and message_processor (0.001 s). close() shut down two of them but left current_session_runner alive, so every instance leaked one 100 ms-loop thread. In long-running watchers that recreate the client (e.g. on transient disconnects detected via is_connected()) those threads accumulate and drive CPU usage up.

This PR adds a guarded current_session_runner.shutdown() call alongside the existing two, plus a regression test verifying that all three runners exit after close().

Closes #1873

Verification

import threading, time
from slack_sdk.socket_mode.builtin.client import SocketModeClient

baseline = threading.active_count()
for _ in range(10):
    SocketModeClient(app_token="xapp-fake").close()
time.sleep(0.3)
# Before this patch: delta = 10. After: delta = 0.
print("delta =", threading.active_count() - baseline)

The added unit test test_close_shuts_down_all_runners covers this in the existing tests/slack_sdk/socket_mode/test_builtin.py.

Requirements

  • Tests added
  • CLA — will be signed at cla.salesforce.com after this PR is opened

`SocketModeClient` starts three `IntervalRunner` threads in
`__init__`: `current_session_runner` (interval 0.1 s),
`current_app_monitor` (interval = `ping_interval`, default 5 s) and
`message_processor` (interval 0.001 s). `close()` shut down two of
them but not `current_session_runner`, so every instance leaked one
thread running a 100 ms loop.

For long-running watchers that recreate the client occasionally (e.g.
after a transient disconnect detected via `is_connected()`), the
leaked threads accumulate and combine with the live instance's 1 ms
`message_processor` loop to drive CPU usage up. The same client
instances also fail to release their threads under normal lifetime
management.

Adds a guarded `current_session_runner.shutdown()` call alongside the
existing two, plus a regression test verifying that all three runners
exit after `close()`.

Closes slackapi#1873
@animaartificialis animaartificialis requested a review from a team as a code owner May 13, 2026 18:15
@salesforce-cla
Copy link
Copy Markdown

Thanks for the contribution! Before we can merge this, we need @animaartificialis to sign the Salesforce Inc. Contributor License Agreement.

@hello-ashleyintech
Copy link
Copy Markdown
Contributor

hi @animaartificialis! Thank you so much for your submission. Could you make sure you sign the CLA?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SocketModeClient.close() leaks current_session_runner thread (built-in client)

2 participants