issue: 4923648 Fix segfault: Ultra API sockets coexist w/ worker threads#593
issue: 4923648 Fix segfault: Ultra API sockets coexist w/ worker threads#593tomerdbz wants to merge 1 commit into
Conversation
a9673c6 to
6039eb3
Compare
Greptile SummaryThis PR fixes a segfault that occurs when Ultra API sockets coexist with XLIO worker threads. The root cause was that
Confidence Score: 5/5The fix is minimal and surgical — one new predicate method, four call-site replacements — and all four thread-mode guards in the connect/listen/accept code paths have been updated consistently. The new should_use_threads_mode() correctly composes the existing is_threads_mode() (confirmed equivalent to worker_threads > 0) with the !m_is_xlio_socket guard. Both the POSIX socket path (behavior unchanged) and the Ultra API socket path (dispatch skipped) are correctly handled. The regression test adds a meaningful negative assertion with a positive 'test was not vacuous' check. No issues found in the changed code paths. No files require special attention. The core change in sockinfo_tcp.cpp is straightforward and fully covered by the new regression test. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["sockinfo_tcp::connect / listen / accept_helper"]
B{"should_use_threads_mode()\nis_threads_mode() && !m_is_xlio_socket"}
C["Worker-thread dispatch path\n(distribute_socket / harvest_sockinfo_tcp_listen_objects\nassert m_syn_received.empty())"]
D["Standard path\n(connect_threads_mode skipped / attach_as_uc_receiver\nremove_received_syn_socket)"]
E["POSIX socket\nm_is_xlio_socket == false"]
F["Ultra API socket\nm_is_xlio_socket == true"]
A --> B
E --> B
F --> B
B -->|"true (POSIX + worker_threads>0)"| C
B -->|"false (Ultra API OR no worker threads)"| D
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["sockinfo_tcp::connect / listen / accept_helper"]
B{"should_use_threads_mode()\nis_threads_mode() && !m_is_xlio_socket"}
C["Worker-thread dispatch path\n(distribute_socket / harvest_sockinfo_tcp_listen_objects\nassert m_syn_received.empty())"]
D["Standard path\n(connect_threads_mode skipped / attach_as_uc_receiver\nremove_received_syn_socket)"]
E["POSIX socket\nm_is_xlio_socket == false"]
F["Ultra API socket\nm_is_xlio_socket == true"]
A --> B
E --> B
F --> B
B -->|"true (POSIX + worker_threads>0)"| C
B -->|"false (Ultra API OR no worker threads)"| D
Reviews (12): Last reviewed commit: "issue: 4923648 Fix segfault: Ultra API s..." | Re-trigger Greptile |
d5d9978 to
7432102
Compare
|
bot:retest |
2a9d52e to
9d2a8b1
Compare
9d2a8b1 to
5e7675e
Compare
5e7675e to
be8c425
Compare
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
be8c425 to
ff44d59
Compare
|
bot:retest |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/gtest/common/subprocess_test.h (1)
7-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHeader isn't self-contained.
subprocess_test.husestesting::Test(Line 21) andunlink()(Line 36) without including<gtest/gtest.h>or<unistd.h>. It currently compiles only because both consumers happen to include these transitively first; any new consumer that includes this header without that ordering would fail to build.♻️ Proposed fix
+#include <gtest/gtest.h> +#include <unistd.h> `#include` <cstdlib> `#include` <fstream> `#include` <string> `#include` "common/def.h"Also applies to: 21-38
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/gtest/common/subprocess_test.h` around lines 7 - 15, `subprocess_test.h` is not self-contained because `SubprocessTest` inherits from `testing::Test` and uses `unlink()` without including their defining headers. Update the header to include the proper declarations directly so it can stand on its own, specifically by adding the missing gtest and POSIX header alongside the existing includes. Keep the fix localized to the `SubprocessTest` definition and its use of `unlink()`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/sock/sockinfo_tcp.cpp`:
- Around line 3344-3345: Keep the accept cleanup gated by the same threads-mode
predicate used in the listen/receive path. In
sockinfo_tcp::sockinfo_tcp::rx_wait/related accept handling, replace the raw
safe_mce_sys().worker_threads check with should_use_threads_mode() so Ultra API
sockets follow the same branch as harvest_sockinfo_tcp_listen_objects(). Make
sure remove_received_syn_socket(ns) still runs whenever the threads-mode path is
active, preventing stale non-thread accept state and related assertions.
In `@tests/gtest/xlio_ultra_api/xlio_socket_worker_threads.cc`:
- Around line 44-46: The test docstring for xlio_socket_worker_threads is out of
sync with the actual assertions: it claims both "connect_socket_job" and "New
TCP socket added" are checked, but only one marker is currently verified. Update
the test body in the socket worker thread regression test to explicitly assert
the absence of the "New TCP socket added" dispatch message as well, keeping the
comments and assertions aligned and covering the entity_context marker alongside
the existing vlist/crash checks.
---
Nitpick comments:
In `@tests/gtest/common/subprocess_test.h`:
- Around line 7-15: `subprocess_test.h` is not self-contained because
`SubprocessTest` inherits from `testing::Test` and uses `unlink()` without
including their defining headers. Update the header to include the proper
declarations directly so it can stand on its own, specifically by adding the
missing gtest and POSIX header alongside the existing includes. Keep the fix
localized to the `SubprocessTest` definition and its use of `unlink()`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Enterprise
Run ID: 26b9b596-b3cf-4232-9066-f46570c20f26
📒 Files selected for processing (9)
.gitignoresrc/core/sock/sockinfo.hsrc/core/sock/sockinfo_tcp.cpptests/gtest/Makefile.amtests/gtest/common/subprocess_test.htests/gtest/output/config.cctests/gtest/xlio_ultra_api/config-ultra-api-worker-threads.jsontests/gtest/xlio_ultra_api/ultra_api_connect_worker_threads_helper.ctests/gtest/xlio_ultra_api/xlio_socket_worker_threads.cc
|
bot:retest |
ff44d59 to
432a521
Compare
|
The three open review threads here were filed against the pre-squash commit
@orshemesh-grok could you re-review |
When worker_threads > 0, XLIO unconditionally dispatches any socket's connect/listen/accept operations to worker threads via distribute_socket(). Ultra API sockets manage their own poll groups and rings, so this dispatch causes double-ownership: the application thread drives the socket through its poll_group while the worker thread also tries to manage it. This leads to "Buff is already a member in a list!" errors and a SIGSEGV in TCP_EVENT_ERR when the worker thread invokes a NULL callback. Add sockinfo::should_use_threads_mode() which returns true only when worker threads are configured AND the socket is not an Ultra API socket (m_is_xlio_socket == false). Replace the three bare is_threads_mode() / worker_threads > 0 checks in sockinfo_tcp.cpp (connect, listen, accept paths) with this new method, allowing POSIX and Ultra API sockets to coexist safely when worker threads are enabled. Add a regression test -ultra_api_worker_threads.no_distribute_on_connect that exercises xlio_socket_connect() with worker_threads=1 at debug log level and asserts that worker-thread dispatch messages are absent from the output. Extract subprocess test infrastructure from output/config.cc into common/subprocess_test.h for reuse. Signed-off-by: Tomer Cabouly <tcabouly@nvidia.com>
432a521 to
c944f3b
Compare
Description
When worker_threads > 0, XLIO unconditionally dispatches any socket's connect/listen/accept operations to worker threads via distribute_socket(). Ultra API sockets manage their own poll groups and rings, so this dispatch causes double-ownership: the application thread drives the socket through its poll_group while the worker thread also tries to manage it. This leads to "Buff is already a member in a list!" errors and a SIGSEGV in TCP_EVENT_ERR when the worker thread invokes a NULL callback.
Add sockinfo::should_use_threads_mode() which returns true only when worker threads are configured AND the socket is not an Ultra API socket (m_is_xlio_socket == false). Replace the three bare is_threads_mode() / worker_threads > 0 checks in sockinfo_tcp.cpp (connect, listen, accept paths) with this new method, allowing POSIX and Ultra API sockets to coexist safely when worker threads are enabled.
Add a regression test -ultra_api_worker_threads.no_distribute_on_connect that exercises xlio_socket_connect() with worker_threads=1 at debug log level and asserts that worker-thread dispatch messages are absent from the output. Extract subprocess test infrastructure from output/config.cc into common/subprocess_test.h for reuse.
What
Skip worker-thread dispatch for Ultra API sockets, preventing SIGSEGV when Ultra API and worker threads coexist.
Why ?
When worker_threads > 0, XLIO unconditionally dispatches any socket's connect/listen/accept to worker threads via distribute_socket(). Ultra API sockets manage their own poll groups and rings, so this dispatch causes double-ownership: the application thread drives the socket through its poll_group while a worker thread also tries to manage it. This leads to "Buff is already a member in a list!" errors and a SIGSEGV in TCP_EVENT_ERR when the worker thread invokes a NULL callback. See Redmine #4923648.
How ?
Add sockinfo::should_use_threads_mode() which returns true only when worker threads are configured and the socket is not an Ultra API socket (!m_is_xlio_socket). Replace the three bare is_threads_mode() / worker_threads > 0 checks in sockinfo_tcp.cpp (connect, listen, accept paths) with this method. POSIX sockets continue to be dispatched to worker threads as before; Ultra API sockets bypass the dispatch entirely.
A regression test (ultra_api_worker_threads.no_distribute_on_connect) launches a helper binary that calls xlio_socket_connect() with worker_threads=1 at debug log level, then asserts that worker-thread dispatch messages (connect_socket_job) are absent from the output. The test runs automatically in CI under the ultra_api* filter with real RDMA addresses and root privileges. Subprocess test infrastructure is extracted from output/config.cc into common/subprocess_test.h for reuse.
Change type
What kind of change does this PR introduce?
Check list
Summary by CodeRabbit
Bug Fixes
Tests