Skip to content

Commit 8e5747f

Browse files
committed
Fix freeze in CRenderWareSA::TxdForceUnload
1 parent 7be6d05 commit 8e5747f

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

Client/game_sa/CRenderWareSA.cpp

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,27 +1121,58 @@ void CRenderWareSA::TxdForceUnload(ushort usTxdId, bool bDestroyTextures)
11211121
if (!pTxd)
11221122
return;
11231123

1124-
// We can abandon the textures instead of destroy. It might be safer, but will cause a memory leak
1124+
constexpr int kMaxTextureUnrefs = 10000;
1125+
constexpr int kMaxTxdUnrefs = 1000;
1126+
11251127
if (bDestroyTextures)
11261128
{
1127-
// Unref the textures
11281129
std::vector<RwTexture*> textureList;
1129-
pGame->GetRenderWareSA()->GetTxdTextures(textureList, pTxd);
1130-
for (std::vector<RwTexture*>::iterator iter = textureList.begin(); iter != textureList.end(); iter++)
1130+
GetTxdTextures(textureList, pTxd);
1131+
for (RwTexture* pTexture : textureList)
11311132
{
1132-
RwTexture* pTexture = *iter;
1133-
while (pTexture->refs > 1)
1133+
if (!pTexture)
1134+
continue;
1135+
1136+
if (pTexture->refs < 1)
1137+
continue;
1138+
1139+
int textureUnrefCount = 0;
1140+
while (pTexture->refs > 1 && textureUnrefCount < kMaxTextureUnrefs)
1141+
{
1142+
RwTextureDestroy(pTexture);
1143+
++textureUnrefCount;
1144+
}
1145+
1146+
int remainingRefs = pTexture->refs;
1147+
if (textureUnrefCount >= kMaxTextureUnrefs && remainingRefs > 1)
1148+
{
1149+
AddReportLog(8625, SString("TxdForceUnload: Texture unref limit hit for TXD %d (refs remaining: %d)", usTxdId, remainingRefs));
1150+
continue;
1151+
}
1152+
1153+
if (remainingRefs == 1)
11341154
RwTextureDestroy(pTexture);
1135-
RwTextureDestroy(pTexture);
11361155
}
11371156
}
11381157

1139-
// Need to have at least one ref for RemoveRef to work correctly
11401158
if (CTxdStore_GetNumRefs(usTxdId) == 0)
11411159
CRenderWareSA::DebugTxdAddRef(usTxdId);
11421160

1143-
while (CTxdStore_GetNumRefs(usTxdId) > 0)
1161+
int txdUnrefCount = 0;
1162+
while (CTxdStore_GetNumRefs(usTxdId) > 0 && txdUnrefCount < kMaxTxdUnrefs)
1163+
{
11441164
CRenderWareSA::DebugTxdRemoveRef(usTxdId);
1165+
++txdUnrefCount;
1166+
}
1167+
1168+
if (txdUnrefCount >= kMaxTxdUnrefs)
1169+
{
1170+
int remainingTxdRefs = CTxdStore_GetNumRefs(usTxdId);
1171+
if (remainingTxdRefs > 0)
1172+
{
1173+
AddReportLog(8626, SString("TxdForceUnload: TXD unref limit hit for TXD %d (refs remaining: %d)", usTxdId, remainingTxdRefs));
1174+
}
1175+
}
11451176
}
11461177

11471178
namespace

0 commit comments

Comments
 (0)