Skip to content

Fix HookEntityOutput/HookSingleEntityOutput bugs in sdktools.#1074

Merged
KyleSanderson merged 1 commit intoalliedmodders:masterfrom
BotoX:bugfix-HookEntityOutput
Feb 27, 2020
Merged

Fix HookEntityOutput/HookSingleEntityOutput bugs in sdktools.#1074
KyleSanderson merged 1 commit intoalliedmodders:masterfrom
BotoX:bugfix-HookEntityOutput

Conversation

@BotoX
Copy link
Contributor

@BotoX BotoX commented Sep 2, 2019

from #sourcemod irc log 2017-03-03:

[15:02:04] <BotoX> so there is clearly something rong with sdktools_entoutput
[15:02:18] <BotoX> HookSingleEntityOutput sometimes doesn't fire
[15:02:29] <BotoX> and HookEntityOutput sometimes fires for the wrong thing
[15:08:02] <psychonic> I think at least the former has been known for a while, but no one has been able to work out the cause, largely due to the issue being very intermittent
[15:11:48] <asherkin> I've heard both of those - I thought they were fixed
[15:14:26] <BotoX> running latest master branch so guess not
[15:14:39] <BotoX> and yeah i wasn't able to reproduce in single player
[15:16:11] <asherkin> BotoX: try searching the tracker
[15:18:22] <psychonic> asherkin: i don't remember anything being fixed with those
[15:28:11] <Fyren> Looking at the code history, not much has changed in a long time.
[15:32:26] <Fyren> https://forums.alliedmods.net/showthread.php?t=168696
[15:32:31] <Fyren> I remember nothing about this even though I replied.
[15:33:19] <BotoX> well
[15:33:22] <BotoX> it randomly fires
[15:33:56] <BotoX> or rather
[15:33:59] <BotoX> most of the time it works
[15:34:02] <BotoX> and sometimes it doesn't :D

[19:46:53] <BotoX> I think I'll just get rid of the "fast lookup" in sdktools EntityOutputManager
[19:48:26] <BotoX> it saves the raw address of the entity object in a trie
[19:48:44] <BotoX> but i don't see it deleting it anywhere when that entity dies
[19:49:05] <BotoX> so if that entity dies and another one is created
[19:49:09] <BotoX> it'd have the same address, no?
[19:49:15] <BotoX> as they're all in the same fat array
[19:52:20] <psychonic> yuck
[19:59:24] <Fyren> BotoX: Looking at the code, the trie holds a list of hooks.
[19:59:29] <Fyren> There's no reason to remove things from the trie.
[19:59:39] <Fyren> The list of hooks has references and they do get cleaned up.
[19:59:52] <BotoX> Q_snprintf(sOutput, sizeof(sOutput), "%p", pOutput);
[19:59:57] <BotoX> pOutput == this of entity
[20:00:02] <BotoX> EntityOutputs->Retrieve(sOutput, (void **)&pOutputName)
[20:02:06] <Fyren> "Saved in a trie" is not the same as "key for the trie."
[20:02:25] <BotoX> well a key is also saved in the trie :^^^^^^^^^^^^^^)
[20:02:41] <Fyren> I would not say so, no.
[20:02:58] <BotoX> anyways, that looks wrong, does it?
[20:03:03] <Fyren> It could be.
[20:20:51] <BotoX> are you looking into this Fyren, else I will just rip the "fast lookup" out of there
[20:20:55] <BotoX> throw it on the server
[20:20:58] <BotoX> and if the issues are gone
[20:21:01] <BotoX> report back
[20:24:35] <Fyren> BotoX: I'm kind of looking, but am very unconvinced the lookup matters.
[20:25:12] <BotoX> inserting memory addresses of entities into a trie
[20:25:15] <BotoX> idk 
[20:25:25] <BotoX> i don't trust that at all
[20:25:50] <Fyren> It's not right but I don't think it'd break the hook.
[20:26:23] <Fyren> The addresses are of the output objects, not the actual entities, not that it's really any different.
[20:26:27] <BotoX> but it might be the reason for it firing completly wrong stuff
[20:26:49] <Fyren> It iterates all the saved hooks for the address and checks the ent refs.
[20:27:10] <Fyren> If the saved ent ref doesn't match the ref of what actually called the output, then it removes that hook entry.
[20:27:28] <Fyren> If the entity dies and that address is never reused, it does leak that memory, effectively.
[20:27:31] <BotoX> ah i see yeah
[20:27:50] <BotoX> but then 
[20:27:53] <BotoX> it got the wrong thing
[20:28:00] <BotoX> so it wouldn't fire that one time
[20:28:02] <BotoX> and next round
[20:28:04] <BotoX> it'd fire again
[20:28:10] <BotoX> this is actually kinda the behavior i was seeing
[20:28:36] <Fyren> The next time the detour happens, it'll check the ref.
[20:28:50] <Fyren> If you hooked a single entity, the ref could be different but then that's your fault.
[20:29:01] <BotoX> i hook single entities
[20:29:08] <BotoX> and what would be my fault lol
[20:29:20] <Fyren> If every round your entity gets killed and recreated.
[20:29:32] <BotoX> oh yeah i hook it onentitycreated every round
[20:29:36] <BotoX> right i am stupid
[20:29:48] <BotoX> so this is not the issue
[20:29:54] <Fyren> If you add the hook every round, then the second time around it skips the first old/dead hook.
[20:29:57] <Fyren> The ref won't match.
[20:30:01] <Fyren> Then removes it from the list.
[20:30:18] <Fyren> But it intends to still go through the whole list and should find the newer entry.
[20:31:05] <BotoX> though i think it is getting the wrong OutputNameStruct
[20:31:16] <BotoX> so my hook is not even in the list
[20:33:54] <Fyren> What output do you think it's missing?
[20:34:11] <Fyren> Can you write a script that like creates/hooks/makes the output happen/kills and repeats?
[20:35:08] <BotoX> it's getting the OutputNameStruct with all the hooks of that output
[20:35:15] <BotoX> using the address of the output
[20:35:20] <BotoX> now if that output was free'd
[20:35:32] <BotoX> and a new one allocd on that address
[20:37:27] <BotoX> / same entity index but different reference. Entity has changed, kill the hook.
[20:37:30] <BotoX> in this case
[20:37:36] <Fyren> If a totally different output landed on that address, maybe you could get additional incorrect callbacks.
[20:37:44] <BotoX> which i am also seeing
[20:37:57] <BotoX> HookEntityOutput("env_entity_maker", "OnEntitySpawned", OnEnvEntityMakerEntitySpawned);
[20:38:07] <Fyren> The output name would be wrong so it'd be easy to notice when it did happen.
[20:38:12] <BotoX> getting random other shit calling OnEnvEntityMakerEntitySpawned
[20:38:49] <BotoX> let me grep my logs for that 
[20:39:50] <BotoX> grep "\[SOURCEMOD BUG\] output:" errors_201* | wc -l
[20:39:50] <BotoX> 1299
[20:40:34] <BotoX> errors_20170213.log:L 02/13/2017 - 11:57:17: [BossHP.smx] [SOURCEMOD BUG] output: "OnEntitySpawned", caller: 975, activator: 975, delay: 0.000000, classname: "point_spotlight"
[20:40:34] <BotoX> errors_20170213.log:L 02/13/2017 - 11:58:36: [BossHP.smx] [SOURCEMOD BUG] output: "OnEntitySpawned", caller: 577, activator: 2, delay: 0.000000, classname: "func_breakable"
[20:40:40] <BotoX> i stopped logging it a while ago
[20:41:04] <BotoX> I am pretty sure a point_spotlight or func_breakable can not fire OnEntitySpawned :)
[20:41:18] <BotoX> and they sure as hell are not env_entity_maker either heh
[20:41:43] <Fyren> Are you hooking that globally or single?
[20:41:53] <BotoX> that is global
[20:41:55] <BotoX> <BotoX> HookEntityOutput("env_entity_maker", "OnEntitySpawned", OnEnvEntityMakerEntitySpawned);
[20:42:07] <BotoX> on single i don't think i am getting wrong calls
[20:42:12] <Fyren> I think the extra wrong callbacks would only happen globally.
[20:42:12] <BotoX> well it wouldn't matter since i filter them so idk
[20:42:18] <BotoX> but on single i am missing calls
[20:47:57] <Fyren> Anyway, a way to reproduce is better than trying shots in the dark.
[20:48:35] <Fyren> The extra callbacks could have a low-effort fix by adding the class name and checking it.
[20:49:11] <BotoX> the effort to reproduce is a lot higher
[20:49:17] <BotoX> than just removing the code that looks fishy to me
[20:49:57] <Fyren> Changing code because of "who knows" probably won't motivate anyone to commit it.
[20:50:06] <BotoX> well if it works after that
[20:50:13] <Fyren> Could change the trie to use a string for the key instead with the classname + outputname.
[20:50:13] <BotoX> then i know if that is at fault
[20:50:14] <BotoX> or not
[20:50:32] <BotoX> and look into it more
[20:50:40] <BotoX> without trying to write tests blind
[20:57:59] <Fyren> If you change the key, I'll review and commit.  It'll at least fix the extra callbacks.
[20:58:19] <Fyren> If you just remove the lookup and keep a single, giant list of every output hook, not really.
[20:59:44] <Fyren> But first, the post office.
[21:00:33] <BotoX> well all i did now was completely remove the fast lookup
[22:21:46] <BotoX> so far no issues by removing fast lookup
[22:21:48] <BotoX> fixed™
[22:21:54] <BotoX> not like that shit is needed anyways

@BotoX BotoX force-pushed the bugfix-HookEntityOutput branch from 911ade1 to ed598e9 Compare September 10, 2019 09:26
@KyleSanderson KyleSanderson requested a review from Fyren November 6, 2019 06:26
@KyleSanderson KyleSanderson self-assigned this Nov 6, 2019
Copy link
Contributor

@Fyren Fyren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no one else cares or has any input about this, I guess it's fine. I'd prefer to replace the trie key with something that's more obviously correct (as in unique), but I don't know if anyone will do it.

Kyle flagged me for review just when I had moved and then I didn't see this in the mass of SP bugmail over the last month. Whoops.

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.

3 participants