I have a manual hook in my extension declared this way:
PHP Code:
SH_DECL_MANUALHOOK2_void(CPlayer_PlayerRunCmd, 0, 0, 0, CUserCmd*, void*)
CPlayer::CPlayer(CBaseEntity* entity)
{
SH_ADD_MANUALHOOK(CPlayer_PlayerRunCmd, GetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}
CPlayer::~CPlayer(void)
{
SH_REMOVE_MANUALHOOK(CPlayer_PlayerRunCmd, GetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}
void CPlayer::OnPlayerRunCmd(CUserCmd *cmd, void *moveHelper)
{
const int pressedButtons = GetButtonPressed();
if(pressedButtons & IN_RELOAD)
{
CBaseEntity* activeWeapon = GetActiveWeaponPointer();
if(!activeWeapon || strcmp(activeWeapon->GetClassName(), "weapon_knife") != 0)
RETURN_META(MRES_IGNORED);
CBaseEntity* ak47 = GetWeaponByClassname("weapon_ak47");
if(!ak47)
RETURN_META(MRES_IGNORED);
SH_MCALL(GetBaseEntity(), CPlayer_Weapon_Switch)(ak47, 0);
}
RETURN_META(MRES_IGNORED);
}
This works, but quite often crashes the server. On in the crashstack I always see the same funtion name and the same stack:
PHP Code:
0 server.so + 0x5d5463
1 server.so + 0x760f0b
2 server.so + 0x767b7a
3 server.so + 0xb8f9e7
4 sdkhooks.ext.2.csgo.so + 0x1bdfe
5 server.so + 0x77c1d3
6 server.so + 0x77c951
7 server.so + 0x75f47c
8 server.so + 0xb8c335
9 extension18.ext.2.csgo.so + 0x35f91
10 server.so + 0x777a94
11 server.so + 0x734db5
The function where crash begins (extension18.ext.2.csgo.so + 0x35f91) Scroll to the comment (// Crashes here)
PHP Code:
int __cdecl __SourceHook_MFHCls_CPlayer_PlayerRunCmd::Func(int a1, int a2, int a3)
{
int v3; // eax@1
int v4; // ebx@1
int (__cdecl *v5)(int, int, int); // edx@2
int v6; // eax@3
int (__cdecl *v7)(int, int, int); // edx@10
int v8; // eax@11
int v10; // [sp+8h] [bp-28h]@1
int v11; // [sp+Ch] [bp-24h]@1
int v12; // [sp+10h] [bp-20h]@1
void (__cdecl *v13)(int, int, int); // [sp+14h] [bp-1Ch]@1
v12 = 0;
v3 = (*(int (__cdecl **)(int, int, int, int, void (__cdecl **)(int, int, int), int *, int *, int *, _DWORD, _DWORD))(*(_DWORD *)g_SHPtr + 76))(
g_SHPtr,
__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_HI,
*(_DWORD *)(a1 + *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[12])
+ 4 * *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[8],
a1,
&v13,
&v12,
&v11,
&v10,
0,
0);
v11 = 0;
v4 = v3;
while ( 1 )
{
v6 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
if ( !v6 )
break;
v10 = 0;
v5 = *(int (__cdecl **)(int, int, int))(*(_DWORD *)v6 + 8);
if ( v5 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
{
v5 = *(int (__cdecl **)(int, int, int))(v6 + 8);
v6 = *(_DWORD *)(v6 + 4) + *(_DWORD *)(v6 + 12);
if ( (unsigned __int8)v5 & 1 )
v5 = *(int (__cdecl **)(int, int, int))((char *)v5 + *(_DWORD *)v6 - 1);
}
v5(v6, a2, a3);
v11 = v10;
if ( v10 > v12 )
v12 = v10;
}
if ( v12 != 3 && (unsigned __int8)(*(int (__cdecl **)(int))(*(_DWORD *)v4 + 12))(v4) )
{
if ( (unsigned __int8)v13 & 1 )
(*(void (__cdecl **)(int, int, int))((char *)v13 + *(_DWORD *)a1 - 1))(a1, a2, a3);
else
v13(a1, a2, a3); // Crashes here
}
v11 = 0;
while ( 1 )
{
v8 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
if ( !v8 )
break;
v10 = 0;
v7 = *(int (__cdecl **)(int, int, int))(*(_DWORD *)v8 + 8);
if ( v7 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
{
v7 = *(int (__cdecl **)(int, int, int))(v8 + 8);
v8 = *(_DWORD *)(v8 + 4) + *(_DWORD *)(v8 + 12);
if ( (unsigned __int8)v7 & 1 )
v7 = *(int (__cdecl **)(int, int, int))((char *)v7 + *(_DWORD *)v8 - 1);
}
v7(v8, a2, a3);
v11 = v10;
if ( v10 > v12 )
v12 = v10;
}
return (*(int (__cdecl **)(int, int))(*(_DWORD *)g_SHPtr + 80))(g_SHPtr, v4);
}
Can somebody give me some advice what it could be?
There are some other hooks which I removed from the example: SetTransmit, OnTakeDamage, Weapon_Switch, Weapon_Equip. None of them crashes, but PlayerRunCmd couses crashes in all my extensions. And I don't see any difference.
I thought that it could be not removed CPlayer instance when the CBaseEntity of the attached player stops existing, but the tests show that CPlayer is always deleted before the attached entity is deleted. If I use GameFrame hook instead, then the crashes go away.