Skip to content

[reve] Process and stream scene data in std::thread instead of civetweb thread - #23631

Merged
linev merged 2 commits into
root-project:masterfrom
alja:eve7-connect-stack
Oct 9, 2026
Merged

linev merged 2 commits into
root-project:masterfrom
alja:eve7-connect-stack

Conversation

@alja

@alja alja commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Fix potential crash using builtin civetweb builder. REveManager uses civetweb server threads. On REveManager::WindowConnect callback all scenes are streamed where size of data can exceed 128K. The WindoConnect callback has the heaviest load.

Solution: Spawn new std::thread REveManager::WindowConnect to prepare scene data and send it to client.

Smaller civetweb stack size has been introduced in april 2026, where civetweb was introduced as a ROOT builtin and with its sources taken from git. See commit 519bb93

Below is Claude report of changes in reduced stack size:

Before: civetweb was bundled and compiled straight into RHTTP (net/http/CMakeLists.txt), and nothing defined USE_STACK_SIZE. Civetweb then makes no pthread_attr_setstacksize() call, so its threads got the default stack size, normally 8 MB on Linux.
After: the commit downloads civetweb and builds it with civetweb's own CMake (builtins/civetweb/CMakeLists.txt). That CMake has CIVETWEB_THREAD_STACK_SIZE defaulting to 102400, and passes it on as USE_STACK_SIZE.
The call itself: in the downloaded source (build/builtins/CIVETWEB-prefix/src/BUILTIN_CIVETWEB/src/civetweb.c:5846 and :5875), the thread-creation code then calls pthread_attr_setstacksize(&attr, USE_STACK_SIZE).
Your build: the civetweb build cache in ~/root-dev/master/build has CIVETWEB_THREAD_STACK_SIZE:STRING=102400, and the compile flags contain -DUSE_STACK_SIZE=102400.
So any ROOT build since 2026-04-17 that uses the builtin civetweb runs web-server callbacks, such as REveManager::WindowConnect, on 100 KB stacks. That's where the cling recursion overflowed.

Another fix would be to pass -DCIVETWEB_THREAD_STACK_SIZE=... (or 0 for the system default) from ROOT's builtins/civetweb/CMakeLists.txt. That would go back to the pre-April behaviour for all of ROOT, not just REve, and would be a change for the http maintainers.

alja added 2 commits October 5, 2026 10:07
is below 1 MB, the work moves to the new StreamToNewConnection(), run in
a std::thread with the default stack size, and the calling thread waits
for it. Locking and the order of events are unchanged: the web-server
thread holds no locks when the callback is called, and the helper takes
fServerState.fMutex exactly as before. An exception is rethrown in the
calling thread; if the helper thread cannot be created, the streaming
runs in the calling thread as before, with a warning.
…The kCameraCenterOrigin is the default and backward compatible camera center behaviour.
@alja
alja requested a review from linev as a code owner October 6, 2026 19:04
@alja alja changed the title Eve7 connect stack [reve] Process and stream scene data in std::thread instead of civetweb thread Oct 6, 2026
@alja

alja commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@ferdymercury @linev @osschar
Please check.

@alja

alja commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Note about the second commit 1443bff:

The additional camera center option was introduced related to PR #23556. Due to different use cases camera center (point of orbit movement) can be in the center of bbox or in the origin (0,0,0). With this commit the camera center is preserved to be in origin (0,0,0). The camera center in the overlap visualization macro is set to the center of bounding box.

This change is unrelated to reve civetweb change/first commit.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Test Results

    24 files      24 suites   4d 1h 35m 22s ⏱️
 3 883 tests  3 880 ✅ 0 💤 3 ❌
83 111 runs  83 108 ✅ 0 💤 3 ❌

For more details on these failures, see this check.

Results for commit 1443bff.

@linev linev 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.

PR fixes the symptoms but not the source of the problem.

There is either an object or an array in the stack that takes up a significant amount of memory, or there is a very deep function call recursion that is "eating" up the stack.

Therefore, one should try to find the reason why the stack is being exhausted.

@linev
linev merged commit d103775 into root-project:master Oct 9, 2026
31 of 36 checks passed
@alja

alja commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@linev

PR fixes the symptoms but not the source of the problem.

There is either an object or an array in the stack that takes up a significant amount of memory, or there is a very deep function call recursion that is "eating" up the stack.

Therefore, one should try to find the reason why the stack is being exhausted.

I agree the change does not fully solves the problem. We did not see it until introduction of builtin civetweb. The stack size went from 8M to 100K.

I have clear understanding of stack exhaustion.
On window connect callback all created scenes are looped, the binary and json data is created for all of them and then the data is sent: https://github.com/root-project/root/blob/master/graf3d/eve7/src/REveManager.cxx#L892-L911
You can see in the code fragment where there is loop over all scenes and that the scenes output json and binary json is not dropped after send. This can be corrected. But the problem where scene size would exceed 1M still stasy.

I will open an issue for this so we dontt forget the problem.

@alja

alja commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@linev
I have opened an issue #23673

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.

4 participants