mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 09:49:19 +02:00
Disown the vehicles before deleting their driver.
TDynamicObject::Update() reads ctOwner->Controlling() every frame, but ctOwner is only ever refreshed by CheckVehicles() and cleared only by Dettach(). Both TController::MoveTo() and ~TDynamicObject() delete a controller while the rest of the consist still points at it, so the vehicles keep dereferencing freed memory until some other driver happens to claim them. Seen as a segfault in DynObj.cpp on ctOwner->Controlling()->MainCtrlPosNo after changing cabs through an EN57 with an AI driver in the leading unit: ctOwner was a live-looking pointer into a freed TController, its mvControlling long gone. ~TController() now clears ctOwner on every vehicle still pointing at it. nullptr is what the readers already expect - they fall back on Mechanik or skip the block - and the next CheckVehicles() re-establishes ownership.
This commit is contained in:
@@ -1999,6 +1999,19 @@ void TController::CloseLog()
|
||||
|
||||
TController::~TController()
|
||||
{ // wykopanie mechanika z roboty
|
||||
// ctOwner is refreshed only by CheckVehicles(), so a vehicle left pointing at a deleted driver
|
||||
// keeps being dereferenced every frame until some other one claims it. Disown them here, as
|
||||
// MoveTo() and ~TDynamicObject() both delete a controller out from under a live consist.
|
||||
// nullptr is expected by the readers, which fall back on Mechanik or skip the block outright
|
||||
if( simulation::is_ready
|
||||
&& false == Global.applicationQuitOrder ) {
|
||||
for( auto *vehicle : simulation::Vehicles.sequence() ) {
|
||||
if( vehicle != nullptr
|
||||
&& vehicle->ctOwner == this ) {
|
||||
vehicle->ctOwner = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseLog();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user