alliedmodders / sourcemod

SourceMod - Source Engine Scripting and Administration
http://www.sourcemod.net/
981 stars 423 forks source link

[Feature Request] A method to catch entity lump parse failures #2198

Open ghost opened 3 months ago

ghost commented 3 months ago

https://github.com/alliedmodders/sourcemod/blob/96727a7610a2690b20670264edb737a42f9da110/core/sourcemod.cpp#L425-L434

Plugins like the SourcePawn plugin for Stripper will not be able to make changes if entity lump parsing fails. If there is a method to catch fails developers can find another work around such as reloading the map.

asherkin commented 3 months ago

What parsing failures have you run into that would have been recoverable?

ghost commented 3 months ago

Without SM, some maps sometimes crash on map start with MapEntity_ParseAllEntities: found ? when expecting {.

With SM, instead of crash on map start receive log Map entity lump parsing for failed with error code 1 on position -1 and reloading map fixes it.

Entity lump does write the changes but does not appear in the map.

nosoop commented 3 months ago

The entity lump is packed into the map file, so the general assumption is that a failure in parsing would only come from a malformed map file (which would not be a sometimes-issue that is fixed on a reload).

In your case, you could probably check that EntityLump.Length() == 0 during either OnMapInit() or OnMapStart(). Failures to parse mid-file would return a partly filled entity lump, but neither of those behaviors are strictly specified.

Error code 0 does suggest that parsing returned Status_OK, so I'm not sure how you're hitting this case. If you could list your environment and reproduction steps, that would probably help.

ghost commented 3 months ago

Sorry, meant error code 1. But I will try EntityLump.Length() == 0 as I guess what on position -1 does mean.

nosoop commented 3 months ago

Position -1 would be end-of-file, so either the whole string was consumed (unlikely if you're hitting the parse failure) or the string was empty. Empty string would mean EntityLump.Length() == 0 should work in your case.

ghost commented 3 months ago

Unfortunately didn't work for my case. The map is tr_walkway. Stripper extension can make changes without issue. I am thinking maybe adding the success bool to OnMapInit.

Alienmario commented 1 week ago

I have this error happen on only 1 map, at random (presumably after server has been running for some time).

Console

243872  170172.655221   L 10/18/2024 - 12:58:35: -------- Mapchange to coop_tropic_v2 --------
243873  170172.692781   L 10/18/2024 - 12:58:35: Map entity lump parsing for coop_tropic_v2 failed with error code 1 on position -1
243874  170172.712265   L 10/18/2024 - 12:58:35: [SM] Exception reported: Did not find closing " for keyvalue
243875  170172.712327   L 10/18/2024 - 12:58:35: [SM] Blaming: srccoop.smx
243876  170172.712371   L 10/18/2024 - 12:58:35: [SM] Call stack trace:
243877  170172.712389   L 10/18/2024 - 12:58:35: [SM]   [0] ThrowError
243878  170172.712408   L 10/18/2024 - 12:58:35: [SM]   [1] Line 495, srccoop\levellump::ParseMapEntities
243879  170172.712425   L 10/18/2024 - 12:58:35: [SM]   [2] Line 76, srccoop\manager::CoopManager.OnLevelInit
243880  170172.712442   L 10/18/2024 - 12:58:35: [SM]   [3] Line 304, c:\VCS\SourceCoop\scripting\srccoop.sp::Hook_OnLevelInit

Stack


0   sourcemod.2.hl2dm.so!ConCommandCleaner::UnlinkConCommandBase + 0x11
1   sourcemod.2.hl2dm.so!__SourceHook_FHCls_ICvarUnregisterConCommand0::CMyDelegateImpl::Call + 0x26
2   sourcemod.2.hl2dm.so!__SourceHook_FHCls_ICvarUnregisterConCommand0::Func + 0x90
3   metamod.2.hl2dm.so!SMConVarAccessor::Unregister [console.cpp:146 + 0x14] 
4   metamod.2.hl2dm.so!BaseProvider::UnregisterConCommandBase [provider_ep2.cpp:439 + 0x12] 
5   metamod.2.hl2dm.so!MetamodSource::UnregisterConCommandBase [metamod.cpp:1149 + 0x17] 
6   metamod.2.hl2dm.so!MetamodSource::UnregisterConCommandBase [metamod.cpp:1119 + 0xd] 
7   sourcemod.2.hl2dm.so!CoreProviderImpl::CommandImpl::~CommandImpl [logic_bridge.cpp:65060 + 0x51] 
8   sourcemod.2.hl2dm.so!CoreProviderImpl::~CoreProviderImpl [logic_bridge.cpp:65060 + 0x89] 
9   libc.so.6 + 0x3a333
10  libc.so.6!exit + 0x27
11  libtier0.so!_SpewMessage(SpewType_t, char const*, int, Color const*, char const*, char*) + 0x141
12  libtier0.so!Error + 0x2c
13  server_srv.so!MapEntity_ParseAllEntities(char const*, IMapEntityFilter*, bool) + 0x37c
14  server_srv.so!CServerGameDLL::LevelInit(char const*, char const*, char const*, char const*, bool, bool) + 0x2b4
15  metamod.2.hl2dm.so!__SourceHook_MFHCls_SGD_LevelInit::Func [metamod.cpp:83 + 0x31] 
16  engine_srv.so!CServerPlugin::LevelInit(char const*, char const*, char const*, char const*, bool, bool) + 0xd0
17  engine_srv.so!Host_Changelevel(bool, char const*, char const*) + 0x2b3
18  engine_srv.so!CHostState::State_ChangeLevelMP() + 0x45
19  engine_srv.so!CHostState::FrameUpdate(float) + 0xd1
20  engine_srv.so!HostState_Frame(float) + 0x19
21  engine_srv.so!CEngine::Frame() + 0x38e