Skip to content

fix: guard bot identity hooks during level teardown - #27

Closed
xiaoyueyoqwq wants to merge 1 commit into
XBribo:mainfrom
xiaoyueyoqwq:fix/bot-identity-teardown-lifecycle
Closed

fix: guard bot identity hooks during level teardown#27
xiaoyueyoqwq wants to merge 1 commit into
XBribo:mainfrom
xiaoyueyoqwq:fix/bot-identity-teardown-lifecycle

Conversation

@xiaoyueyoqwq

@xiaoyueyoqwq xiaoyueyoqwq commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Problem

During level shutdown or map transitions, BotHider could access client/controller objects while the engine was already dismantling them. Concurrent shutdown callbacks could also attempt restoration more than once, leading to native crashes in engine modules.

Fix

  • Add an atomic Inactive -> Active -> Teardown lifecycle gate around native and managed callbacks.
  • Serialize teardown restoration so only one callback accesses level-owned entities.
  • Restore managed clients only through a restricted pre-teardown window.
  • Stop resolver, identity, userinfo, deferred removal, GameFrame, and avatar writes once teardown begins.
  • Validate controller class, deletion state, and entity handles before controller flag writes.
  • Discard in-progress population snapshots during teardown.
  • Track in-flight funchook detours and wait for them during unload; remove SourceHook callbacks before destroying native trampolines.
  • Keep the same-map collector hook disabled until its entity lifetime contract is safe to re-enable.

Validation

  • cmake --build build-local -j2 passed.
  • dotnet build csharp/BotHiderImpl/BotHiderImpl.csproj -c Release --no-restore passed with 0 warnings and 0 errors.
  • git diff --check passed.
  • The previously reported post-intermission/no-vote crash was not reproduced with the earlier lifecycle mitigation.
  • Need more test: the new serialized restoration path requires maintainer review and runtime shutdown/map-transition testing on the supported server builds.

@xiaoyueyoqwq
xiaoyueyoqwq requested a review from XBribo as a code owner August 28, 2026 09:31
@XBribo

XBribo commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Disable the same-map hook may reintroduce bot slot leaks. Please consider keeping the hook.

@XBribo

XBribo commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Also, adding an auto_vote config doesn't seem useful. I can't think of any reason to turn it off. ;)

@xiaoyueyoqwq

xiaoyueyoqwq commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Also, adding an auto_vote config doesn't seem useful. I can't think of any reason to turn it off. ;)

You're right: auto_vote_for_managed_bots and the same-map hook are still experimental, highly environment-specific parts of my ongoing debugging, not core BotHider behavior. I’ll keep them disabled for now and properly clean up, document, and either remove or move them into a dedicated follow-up once they are validated, rather than leaving unverified code in this PR.

Sorry for the wrong commit :/

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

Disable the same-map hook may reintroduce bot slot leaks. Please consider keeping the hook.

I noticed this issue too...seems really weird, I'm still looking for the solution and test it on my own server. Thank you for your patience!

@XBribo

XBribo commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Disable the same-map hook may reintroduce bot slot leaks. Please consider keeping the hook.

I noticed this issue too...seems really weird, I'm still looking for the solution and test it on my own server. Thank you for your patience!

When you're ready, feel free to comment again. Thanks for your PR!

@xiaoyueyoqwq

xiaoyueyoqwq commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Disable the same-map hook may reintroduce bot slot leaks. Please consider keeping the hook.

Hi there! First of all, I'd like to state that I'm a new user/developer in the CS2 server community, so there are many things I don't understand. I hope you can patiently explain. I'd like to know exactly what problem you're referring to, because based on my understanding and testing, I haven't been able to reproduce the ghost bot issue on my own server. I've also submitted some fixes and cleaned up the previous messy code; you can use the last commit for the final test.

And I'm apologize again for my previous recklessness. I will further regulate my AI workflow to prevent such a large number of erroneous/off-topic, meaningless commits from happening again.

I also submitted another PR that could cause the server to crash(#29), I'm not sure if there's a strong correlation between the two. Based on my local testing, I haven't observed any functional malfunctions. If you'd like, you can combine the two reports for further analysis.

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

To put it simply... the CS2 server community ecosystem seems exceptionally challenging. Valve doesn't provide many custom APIs, forcing developers to implement these great features in all sorts of bizarre ways. I can't even imagine how they did it; it's practically an engineering marvel, haha... Or rather, it took me a considerable amount of time to successfully set up a CS2 server, so I hope you can understand this complex feeling. This is the most complex and difficult-to-maintain game server I've ever encountered.

In other words, I was initially very confident because I had at least six years of experience in Minecraft server development and maintenance, and I was also an early tester of Papermc Folia. Even the official website of the Folia server downstream frok project LuminoMC's website, was remake by myself... Of course, this may sound like bragging, but I just wanted to lament how things got so messy lol, I hope you don't mind my complaints.

Anyway, thanks for your helping. If there still have any issue just keep tracking. I will do my best

@XBribo

XBribo commented Aug 29, 2026

Copy link
Copy Markdown
Owner

I mean a CServerSideClient/INetworkGameClient slot that remains occupied after a no-vote same-map restart.
BotHider clears the controller’s 0x100 fake-client bit. The same-map path bypasses both StartChangeLevel and OnLevelShutdown. It then checks that bit before restarting the round: bots with 0x100 are disconnected with reason 39, while clients without it are only sent through ChangeTeam(0). The exact same-map hook restored the bot identity immediately before this check.
Therefore, disabling the hook can send managed bots through the human-client path and leave their network slots occupied.

@XBribo

XBribo commented Aug 29, 2026

Copy link
Copy Markdown
Owner

By the way, I also tried Minecraft plugin development haha, but gave up. Folia's multithreading really does have compatibility issues. ;(

@XBribo

XBribo commented Aug 29, 2026

Copy link
Copy Markdown
Owner

By the way, I think CS2-Vote-Improver is pretty nice. Want to integrate it into BotHider?

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

I mean a CServerSideClient/INetworkGameClient slot that remains occupied after a no-vote same-map restart. BotHider clears the controller’s 0x100 fake-client bit. The same-map path bypasses both StartChangeLevel and OnLevelShutdown. It then checks that bit before restarting the round: bots with 0x100 are disconnected with reason 39, while clients without it are only sent through ChangeTeam(0). The exact same-map hook restored the bot identity immediately before this check. Therefore, disabling the hook can send managed bots through the human-client path and leave their network slots occupied.

Got it, I'm still working on it.

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

By the way, I think CS2-Vote-Improver is pretty nice. Want to integrate it into BotHider?

To be honest, that was my initial plan. The 'auto_vote_for_managed_bots' configuration option you see is a remnant from my early attempts to achieve compatibility between the two plugins. However, the problem I'm currently facing is quite real: in Player mode, I simply cannot get the plugin to correctly recognize "this is a Bot and not a Player." In the end, to focus my energy on fixing the current PR issue, I had to make some... trade-offs. Yes, I'm not against merging this functionality into the Bot-Hider plugin, but currently I simply don't have the energy to do it. I'm still continuously tracking the server crash issue caused by BotHider, and it looks quite complex :/

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

Test and scope update

We investigated the shutdown crash that was initially suspected to be caused by BotHider.

The latest PR commit, 40e3f32 (fix: serialize identity restoration during teardown), was tested in identity_mode=bot. The server still reproduced a shutdown fault in libtier0.so +0x32d43. However, the same fault was reproduced after completely disabling BotHider, including both the native VDF and the managed plugin.

The isolation results were:

  • BotHider enabled: shutdown fault reproduced.
  • BotHider and all managed plugins disabled, with CounterStrikeSharp core loaded: shutdown fault reproduced.
  • counterstrikesharp.vdf disabled, leaving the pure CS2 engine: three clean shutdowns completed without a fault.

This means the shutdown crash is currently most consistent with a CounterStrikeSharp core/engine interaction, and it should not be attributed to BotHider.

The latest PR commit should therefore be considered a narrowly scoped, potentially safe lifecycle hardening change, but not as a confirmed fix for the libtier0.so shutdown crash. I recommend keeping it available for maintainer review and marking it Need more test. Further validation should focus on the exact identity teardown and same-map slot cleanup paths independently from the CounterStrikeSharp shutdown issue.

@XBribo

XBribo commented Aug 29, 2026

Copy link
Copy Markdown
Owner

So is the issue with CounterStrikeSharp? ;(

@xiaoyueyoqwq

xiaoyueyoqwq commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

So is the issue with CounterStrikeSharp? ;(

Yes, this is indeed very frustrating. I checked the CounterStrikeSharp repo and PR, and for some reason they've been putting off merging such a user-unfriendly issue for three months. This is terrible.

However, good news follows: you can now change the PR status to Open. The code appears to be ready for review. Please leave a comment if you have any further questions.I'm still actively reviewing and trying to reproduce the crash issue on my own server, but it appears these issues have been resolved. CounterStrikeSharp orgin PR is #1314

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

However, it's important to distinguish between the server crash issue caused by CounterStrikeSharp and the problem this PR ultimately aims to solve. These are two relatively independent issues and should not be confused.

@XBribo
XBribo marked this pull request as ready for review August 30, 2026 06:15
@XBribo

XBribo commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Also, the code has been refactored. Please resolve the conflicts again and explain the purpose of your changes.

@xiaoyueyoqwq
xiaoyueyoqwq force-pushed the fix/bot-identity-teardown-lifecycle branch from 40e3f32 to 420c0a0 Compare August 30, 2026 08:22
@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

Rebased PR #27 onto the current main (53e2b9a) and resolved the refactor conflicts.

The purpose of this change is limited to lifecycle safety around BotHider's native identity/entity hooks:

  • add an explicit active/teardown lifecycle gate;
  • stop client, command, resolver, identity-write, and population-transaction work once teardown starts;
  • serialize the single pre-teardown identity-restore window;
  • discard pending population snapshots instead of restoring through stale entity pointers;
  • track in-flight native detours before uninstalling funchook trampolines;
  • invalidate deferred managed-plugin timers and callbacks across map generations.

No bot-quota or Vote-Improver behavior was added. The existing same-map collector implementation is unchanged by this rebase. Native and C# Release builds pass, and git diff --check is clean.

This is a narrow lifecycle hardening change and should receive additional testing for map transitions, unload/reload, and server shutdown before it is treated as final.

@xiaoyueyoqwq

Copy link
Copy Markdown
Contributor Author

Clarification on the same-map path: this rebase preserves the PR branch's existing decision not to prepare/install the same-map teardown detour. Enabling it may be appropriate for slot cleanup, but that requires a separate, reproducible validation because it runs inside an engine teardown helper with a version-specific ABI; it is intentionally outside this lifecycle-only rebase.

@XBribo

XBribo commented Aug 30, 2026

Copy link
Copy Markdown
Owner

So what problem does this PR actually solve? Please first test whether the current main branch still has any issues after the CSS fix. Also, this PR reverts the latest Bot mode fix and removes avatar::ProcessOverrides(), which may cause avatars to be left undeleted. Please review your PR manually before submitting, this PR will be converted to a draft.

@XBribo
XBribo marked this pull request as draft August 30, 2026 11:23
@xiaoyueyoqwq

xiaoyueyoqwq commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Update, apology, and test results

I owe you a correction. Our initial report attributed the end-of-match no-vote crash to BotHider, and I expanded this PR based on that assumption. That attribution was premature, and the PR history became unnecessarily noisy. Sorry for the confusion and for the extra review burden.

We subsequently repeated the test after updating CounterStrikeSharp and deploying the official BotHider v0.4.1 package:

  1. With BotHider enabled and identity_mode=player, we ran a short match to natural completion, waited for Going to intermission..., and observed the automatic map transition. The CS2 PID did not change. There was no repeated countdown, fallback to dust_2, or new runtime crash.

  2. After restarting, we repeated the same flow with identity_mode=bot and two managed bots. The match reached intermission and automatically changed to another map. The PID remained unchanged and no new segfault or general-protection fault occurred.

  3. To isolate the earlier shutdown fault, we disabled BotHider while keeping CounterStrikeSharp loaded. The same libtier0.so +0x32d43 shutdown fault still reproduced. With CounterStrikeSharp disabled as well, leaving only the CS2 engine, three consecutive clean shutdowns completed.

The end-of-match transition therefore worked in both identity modes in this test, and the shutdown fault was not BotHider-specific based on the control test. We could not observe the client UI directly and had no explicit vote-event log, so we can confirm the automatic map transition but not conclusively prove that the no-vote random-draw animation branch was displayed.

Please treat the lifecycle changes here as unconfirmed hardening, not as a confirmed crash fix. In light of these results, this PR can either remain a draft for reference or be closed; it should not be merged as a fix for the reported crash.

@XBribo

XBribo commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Waiting for CounterStrikeSharp to fix this, the PR will be closed.

@XBribo XBribo closed this Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants