Skip to content

Conversation

@Architector4
Copy link
Contributor

Not doing this can cause a crash due to the a sub pie menu being open when its pie slice is removed.

For example, having a grenade launcher subpiemenu open when the current actor enters a "dying" state causes it to get detached, removing and clearing the subpiemenu, but not removing it as the active subpiemenu. The game then tries to render it and crashes on m_LargeFont being nullptr.

For example, here's a gdb backtrace to where exactly the submenu gets cleared, and then where the game crashes, before this patch:

Details
Thread 1 "CortexCommand" hit Breakpoint 1, RTE::PieMenu::Clear (this=0x5555813c5050) at ../Source/Entities/PieMenu.cpp:55
55		m_LargeFont = nullptr;
#0  RTE::PieMenu::Clear (this=0x5555813c5050) at ../Source/Entities/PieMenu.cpp:55
#1  0x000055555585c4d8 in RTE::PieMenu::Destroy (this=0x5555813c5050, notInherited=true) at ../Source/Entities/PieMenu.cpp:174
#2  0x0000555555871d24 in RTE::PieSlice::PieMenuCustomDeleter::operator() (this=0x55557eb82ac8, pieMenu=0x5555813c5050) at ../Source/Entities/PieSlice.cpp:191
#3  0x00005555558728d9 in std::unique_ptr<RTE::PieMenu, RTE::PieSlice::PieMenuCustomDeleter>::~unique_ptr (this=0x55557eb82ac8) at /usr/include/c++/15.2.1/bits/unique_ptr.h:399
#4  0x000055555586fe6d in RTE::PieSlice::~PieSlice (this=0x55557eb829d0) at ../Source/Entities/PieSlice.cpp:17
#5  0x000055555586feca in RTE::PieSlice::~PieSlice (this=0x55557eb829d0) at ../Source/Entities/PieSlice.cpp:17
#6  0x000055555585edfa in RTE::PieMenu::RemovePieSlicesByOriginalSource (this=0x5555825f5de0, originalSource=0x55557062b730) at ../Source/Entities/PieMenu.cpp:459
#7  0x00005555557b9c96 in RTE::Attachable::AddOrRemovePieSlicesAndListenersFromPieMenu (this=0x55557062b730, pieMenuToModify=0x5555825f5de0, addToPieMenu=false)
    at ../Source/Entities/Attachable.cpp:609
#8  0x00005555557b8e64 in RTE::Attachable::SetParent (this=0x55557062b730, newParent=0x0) at ../Source/Entities/Attachable.cpp:541
#9  0x00005555557f3b3d in RTE::HDFirearm::SetParent (this=0x55557062b730, newParent=0x0) at ../Source/Entities/HDFirearm.h:486
#10 0x000055555582cf54 in RTE::MOSRotating::RemoveAttachable (this=0x55557119cac0, attachable=0x55557062b730, addToMovableMan=true, addBreakWounds=false) at ../Source/Entities/MOSRotating.cpp:1507
#11 0x00005555557b8582 in RTE::Attachable::RemoveAttachable (this=0x55557119cac0, attachable=0x55557062b730, addToMovableMan=true, addBreakWounds=false) at ../Source/Entities/Attachable.cpp:466
#12 0x000055555577d1b4 in RTE::AHuman::Update (this=0x5555717641d0) at ../Source/Entities/AHuman.cpp:2608
#13 0x0000555555ae03c5 in RTE::MovableMan::Update (this=0x555557405d50) at ../Source/Managers/MovableMan.cpp:1405
#14 0x000055555567597c in RunGameLoop () at ../Source/Main.cpp:354
#15 0x000055555567658a in main (argc=1, argv=0x7fffffffdc88) at ../Source/Main.cpp:468

Thread 1 "CortexCommand" received signal SIGSEGV, Segmentation fault.
0x000055555593a220 in RTE::GUIFont::GetFontHeight (this=0x0) at ../Source/GUI/GUIFont.cpp:394
394		return m_FontHeight;

Here's the backtrace of a crash from a debug build of the game:

Details
Stack trace (most recent call last):
#14   Object "", at 0xffffffffffffffff, in
#13   Object "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/CortexCommand", at 0x5588f54d8bb4, in _start
#12   Object "/usr/lib/libc.so.6", at 0x7f790be27c4a, in __libc_start_main
#11   Object "/usr/lib/libc.so.6", at 0x7f790be27b8a, in __libc_init_first
#10   Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Main.cpp", line 468, in main [0x5588f54db589]
        465: 			RunMenuLoop();
        466: 		}
        467:
      > 468: 		RunGameLoop();
        469: 	}
        470:
        471: 	g_ThreadMan.GetPriorityThreadPool().wait_for_tasks();
#9    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Main.cpp", line 395, in RunGameLoop() [0x5588f54daecd]
        392: 		updateTotalTime = updateEndAndDrawStartTime - updateStartTime;
        393: 		drawStartTime = updateEndAndDrawStartTime;
        394:
      > 395: 		g_FrameMan.Draw();
        396: 		g_WindowMan.DrawPostProcessBuffer();
        397: 		g_WindowMan.UploadFrame();
#8    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Managers/FrameMan.cpp", line 870, in RTE::FrameMan::Draw() [0x5588f5905b7c]
        867: 		}
        868:
        869: 		// Draw the scene
      > 870: 		g_SceneMan.Draw(drawScreen, drawScreenGUI, targetPos);
        871:
        872: 		g_PrimitiveMan.DrawPrimitives(playerScreen, drawScreenGUI, targetPos);
#7    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Managers/SceneMan.cpp", line 2630, in RTE::SceneMan::Draw(BITMAP*, BITMAP*, RTE::Vector const&, bool, bool) [0x5588f59b2a92]
       2628: 			bool shouldDrawHUD = !g_FrameMan.IsHudDisabled(m_LastUpdatedScreen);
       2629: 			if (shouldDrawHUD) {
      >2630: 				g_MovableMan.DrawHUD(targetGUIBitmap, targetPos, m_LastUpdatedScreen);
       2631: 			}
       2632:
       2633: 			if (shouldDrawHUD) {
#6    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Managers/MovableMan.cpp", line 1956, in RTE::MovableMan::DrawHUD(BITMAP*, RTE::Vector const&, int, bool) [0x5588f59591f9]
       1953: 		(*itmIt)->DrawHUD(pTargetBitmap, targetPos, which);
       1954:
       1955: 	for (std::deque<Actor*>::reverse_iterator aIt = m_Actors.rbegin(); aIt != m_Actors.rend(); ++aIt)
      >1956: 		(*aIt)->DrawHUD(pTargetBitmap, targetPos, which);
       1957: }
#5    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Entities/AHuman.cpp", line 2687, in RTE::AHuman::DrawHUD(BITMAP*, RTE::Vector const&, int, bool) [0x5588f55e334f]
       2684: 		return;
       2685: 	}
       2686:
      >2687: 	Actor::DrawHUD(pTargetBitmap, targetPos, whichScreen);
       2688:
       2689: 	if (!m_HUDVisible) {
       2690: 		return;
#4    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Entities/Actor.cpp", line 1377, in RTE::Actor::DrawHUD(BITMAP*, RTE::Vector const&, int, bool) [0x5588f55a612b]
       1374: 	int actorScreen = g_ActivityMan.GetActivity() ? g_ActivityMan.GetActivity()->ScreenOfPlayer(m_Controller.GetPlayer()) : -1;
       1375: 	bool screenTeamIsSameAsActorTeam = g_ActivityMan.GetActivity() ? g_ActivityMan.GetActivity()->GetTeamOfPlayer(g_ActivityMan.GetActivity()->PlayerOfScreen(whichScreen)) == m_Team : true;
       1376: 	if (m_PieMenu->IsVisible() && screenTeamIsSameAsActorTeam && (!m_PieMenu->IsInNormalAnimationMode() || (actorScreen == whichScreen))) {
      >1377: 		m_PieMenu->Draw(pTargetBitmap, targetPos);
       1378: 	}
       1379:
       1380: 	if (!m_HUDVisible) {
#3    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Entities/PieMenu.cpp", line 666, in RTE::PieMenu::Draw(BITMAP*, RTE::Vector const&) const [0x5588f56c516b]
        663: 	}
        664:
        665: 	if (m_ActiveSubPieMenu) {
      > 666: 		m_ActiveSubPieMenu->Draw(targetBitmap, targetPos);
        667: 	}
        668: 	rlZDepth(c_DefaultDrawDepth);
        669: }
#2    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Entities/PieMenu.cpp", line 643, in RTE::PieMenu::Draw(BITMAP*, RTE::Vector const&) const [0x5588f56c4e4f]
        640: void PieMenu::Draw(BITMAP* targetBitmap, const Vector& targetPos) const {
        641: 	rlZDepth(c_GuiDepth);
        642: 	Vector drawPos;
      > 643: 	CalculateDrawPosition(targetBitmap, targetPos, drawPos);
        644:
        645: 	rlZDepth(c_GuiDepth);
        646: 	if (m_EnabledState != EnabledState::Disabled) {
#1    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/Entities/PieMenu.cpp", line 957, in RTE::PieMenu::CalculateDrawPosition(BITMAP const*, RTE::Vector const&, RTE::Vector&) const [0x5588f56c74c3]
        954: 	}
        955:
        956: 	// Adjust the draw position so that the menu will always be drawn fully inside the player's screen
      > 957: 	int menuDrawRadius = m_CurrentInnerRadius + m_BackgroundThickness + 2 + m_LargeFont->GetFontHeight();
        958: 	if (drawPos.m_X - static_cast<float>(menuDrawRadius) < 0.0F) {
        959: 		drawPos.m_X = static_cast<float>(menuDrawRadius);
        960: 	} else if (drawPos.m_X + static_cast<float>(menuDrawRadius) > static_cast<float>(targetBitmap->w)) {
#0    Source "/media/ext_hdd/nobackup/architector4/Downloads/Cortex-Command-Community-Project/builddebug/../Source/GUI/GUIFont.cpp", line 394, in RTE::GUIFont::GetFontHeight() const [0x5588f579f220]
        391: }
        392:
        393: int GUIFont::GetFontHeight() const {
      > 394: 	return m_FontHeight;
        395: }
        396:
        397: std::string GUIFont::GetName() const {
Segmentation fault (Address not mapped to object [0x30])
Segmentation fault         prime-run builddebug/CortexCommand

Demonstration of the crash:

tmp.uVp57hVAG6.mp4

I cannot replicate the crash with this patch applied.

Not doing this can cause a crash due to the a sub pie menu being open when its pie slice is removed.

For example, having a grenade launcher subpiemenu open when the current actor enters a "dying" state causes it to get detached, removing and clearing the subpiemenu, but not removing it as the active subpiemenu. The game then tries to render it and crashes on `m_LargeFont` being `nullptr`.

For example, here's a gdb backtrace to where exactly the submenu gets cleared, and then where the game crashes, before this patch:

```
Thread 1 "CortexCommand" hit Breakpoint 1, RTE::PieMenu::Clear (this=0x5555813c5050) at ../Source/Entities/PieMenu.cpp:55
55		m_LargeFont = nullptr;
#0  RTE::PieMenu::Clear (this=0x5555813c5050) at ../Source/Entities/PieMenu.cpp:55
cortex-command-community#1  0x000055555585c4d8 in RTE::PieMenu::Destroy (this=0x5555813c5050, notInherited=true) at ../Source/Entities/PieMenu.cpp:174
cortex-command-community#2  0x0000555555871d24 in RTE::PieSlice::PieMenuCustomDeleter::operator() (this=0x55557eb82ac8, pieMenu=0x5555813c5050) at ../Source/Entities/PieSlice.cpp:191
cortex-command-community#3  0x00005555558728d9 in std::unique_ptr<RTE::PieMenu, RTE::PieSlice::PieMenuCustomDeleter>::~unique_ptr (this=0x55557eb82ac8) at /usr/include/c++/15.2.1/bits/unique_ptr.h:399
cortex-command-community#4  0x000055555586fe6d in RTE::PieSlice::~PieSlice (this=0x55557eb829d0) at ../Source/Entities/PieSlice.cpp:17
cortex-command-community#5  0x000055555586feca in RTE::PieSlice::~PieSlice (this=0x55557eb829d0) at ../Source/Entities/PieSlice.cpp:17
cortex-command-community#6  0x000055555585edfa in RTE::PieMenu::RemovePieSlicesByOriginalSource (this=0x5555825f5de0, originalSource=0x55557062b730) at ../Source/Entities/PieMenu.cpp:459
cortex-command-community#7  0x00005555557b9c96 in RTE::Attachable::AddOrRemovePieSlicesAndListenersFromPieMenu (this=0x55557062b730, pieMenuToModify=0x5555825f5de0, addToPieMenu=false)
    at ../Source/Entities/Attachable.cpp:609
cortex-command-community#8  0x00005555557b8e64 in RTE::Attachable::SetParent (this=0x55557062b730, newParent=0x0) at ../Source/Entities/Attachable.cpp:541
cortex-command-community#9  0x00005555557f3b3d in RTE::HDFirearm::SetParent (this=0x55557062b730, newParent=0x0) at ../Source/Entities/HDFirearm.h:486
cortex-command-community#10 0x000055555582cf54 in RTE::MOSRotating::RemoveAttachable (this=0x55557119cac0, attachable=0x55557062b730, addToMovableMan=true, addBreakWounds=false) at ../Source/Entities/MOSRotating.cpp:1507
cortex-command-community#11 0x00005555557b8582 in RTE::Attachable::RemoveAttachable (this=0x55557119cac0, attachable=0x55557062b730, addToMovableMan=true, addBreakWounds=false) at ../Source/Entities/Attachable.cpp:466
cortex-command-community#12 0x000055555577d1b4 in RTE::AHuman::Update (this=0x5555717641d0) at ../Source/Entities/AHuman.cpp:2608
cortex-command-community#13 0x0000555555ae03c5 in RTE::MovableMan::Update (this=0x555557405d50) at ../Source/Managers/MovableMan.cpp:1405
cortex-command-community#14 0x000055555567597c in RunGameLoop () at ../Source/Main.cpp:354
cortex-command-community#15 0x000055555567658a in main (argc=1, argv=0x7fffffffdc88) at ../Source/Main.cpp:468

Thread 1 "CortexCommand" received signal SIGSEGV, Segmentation fault.
0x000055555593a220 in RTE::GUIFont::GetFontHeight (this=0x0) at ../Source/GUI/GUIFont.cpp:394
394		return m_FontHeight;
```

I cannot replicate the crash with this patch applied.
@Causeless Causeless enabled auto-merge October 28, 2025 21:43
@Causeless Causeless disabled auto-merge October 28, 2025 21:46
@Causeless Causeless merged commit 01fb6b0 into cortex-command-community:development Oct 28, 2025
0 of 4 checks passed
@Architector4 Architector4 deleted the patch-1 branch October 29, 2025 01:10
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