Skip to content

Fix aiohttp Socket Mode close lifecycle#1914

Open
xero-aiescape wants to merge 1 commit into
slackapi:mainfrom
xero-aiescape:fix/aiohttp-socket-mode-close-lifecycle
Open

Fix aiohttp Socket Mode close lifecycle#1914
xero-aiescape wants to merge 1 commit into
slackapi:mainfrom
xero-aiescape:fix/aiohttp-socket-mode-close-lifecycle

Conversation

@xero-aiescape

Copy link
Copy Markdown

Summary

Fixes the aiohttp Socket Mode shutdown race described in #1913.

  • stop connect() once client shutdown begins, including when close lands during an in-flight failed attempt
  • discard and close a WebSocket that completes after the client has already closed instead of installing new monitor/receiver tasks
  • cancel and await the SDK-owned message processor, session monitor, and receiver tasks before closing the aiohttp ClientSession
  • avoid cancelling or awaiting the current task when an owned reconnect task is itself coordinating close
  • preserve normal ping_interval backoff, proxy, SSL, and live connection setup behavior

Testing

  • ./scripts/run_tests.sh tests/slack_sdk_async/socket_mode/test_aiohttp.py — 10 passed
  • ./scripts/run_tests.sh tests/slack_sdk_async/socket_mode/ — 18 passed before the final added close-success race; the final file and full CI-equivalent suite cover that addition
  • CI-equivalent Python 3.14 unit command from .github/workflows/ci-build.yml with AWS host credentials/region removed — 984 passed, 5 skipped
  • ./scripts/run_mypy.sh --no-install — 106 source files clean
  • focused Black/Flake8 and Semgrep Python checks — clean
  • ./scripts/build_pypi_package.sh — sdist/wheel built and twine check passed

Red-before-green lifecycle coverage verifies:

  • an already-closed real aiohttp client returns instead of retrying a closed ClientSession
  • close during a failed connection attempt terminates the orphan-capable task
  • a connection that succeeds after close is discarded and its WebSocket is closed
  • live connection failures still wait for ping_interval
  • close() does not return until all owned task cleanup settles and before the client session closes
  • an owned task coordinating close does not cancel or await itself

Category

  • slack_sdk.socket_mode (Socket Mode client)
  • tests/integration_tests (Automated tests for this library)

Requirements

  • I've read and understood the Contributing Guidelines and have done my best effort to follow them.
  • I've read and agree to the Code of Conduct.
  • I've run the repository validation commands in a repo-local virtual environment after making the changes.

Fixes #1913

@xero-aiescape xero-aiescape requested a review from a team as a code owner July 10, 2026 15:20
@salesforce-cla

Copy link
Copy Markdown

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

Stop connect attempts once client shutdown begins, discard sessions that complete after close, and await cancellation of SDK-owned tasks before closing the aiohttp session.\n\nAdds lifecycle regressions for closed clients, close races, current-task ownership, backoff, and task/session cleanup.\n\nRefs slackapi#1913
@xero-aiescape xero-aiescape force-pushed the fix/aiohttp-socket-mode-close-lifecycle branch from 5177d99 to 5650620 Compare July 10, 2026 15:21

@mwbrooks mwbrooks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @xero-aiescape, thanks for the PR! 🙇🏻

Before we can review your pull request, can you please sign the CLA? ✏️

Thanks!

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 (aiohttp backend): connect() retries forever against a closed ClientSession — orphaned retry loop survives close()

2 participants