nipkownix / re4_tweaks

Fixes and tweaks for the "UHD" port of Resident Evil 4
zlib License
346 stars 32 forks source link

Leaving Movie Browser while in d3d9 with VS debugger attached causes exception #378

Open pas-de-2 opened 1 year ago

pas-de-2 commented 1 year ago

No idea what's going on here. I checked out a few commits and it looks like this started happening with the DXVK integration.

Doesn't happen without the debugger attached, doesn't happen with Vulkan, ~doesn't happen in windowed mode.~ E: it happens while windowed as well, but inconsistently.

Capture

Here's a bio4.dmp: https://gofile.io/d/H8ahr0

emoose commented 1 year ago

Hm, I noticed when I ran debug builds under VS debugger it would usually show an exception when exiting too, something to do with our input code I think (maybe handle_window_message iirc?), that only started happening with the DXVK integration too.

emoose commented 1 year ago

Seems the OP crash is something inside XAudio2_XACTCUE_GetState - been having crashes there since before DXVK was added afaik - might have started with the trainer stuff (or maybe framelimiter change?) Mostly seems to happen to me when loading into a stage from main menu, I guess exiting the movie browser might be reloading r120 which then also has a chance of running into this.

Looks like Cue_8 in that func points to something invalid, and then when it fetches GetState addr from vftable it gets another invalid addr and then jumps to it, not sure what could cause that though...

Since it's usually when stage is being loaded, I guess that would also require previous stage to be unloaded, maybe unload is freeing all the Cue stuff while sound code is still trying to read from them at the same time (sound stuff does run in a separate thread...)

Maybe will need to figure out how that Cue stuff gets uninited and check whether it's actually signalling that the sound stuff should stop properly.

emoose commented 1 year ago

Ah seems the unrelated crash-on-exit that I mentioned might not be DXVK related, issue happens at the erase call here: https://github.com/nipkownix/re4_tweaks/blob/15ba4d24c46137220aa56268c77bd361a20ef688/dllmain/input.cpp#L99-L105

Seems s_windows vector is invalid there some reason, tried checking all the things that would insert/remove from it but nothing seemed to be interacting at the same time.

Eventually tried setting a data breakpoint on the pointer inside it, and VS showed it getting hit by the s_windows destructor: devenv_22-12-09_04-29-22-871

So I guess the input::handle_window_message code I linked might be trying to access it after the dtor has ran? But it doesn't always, eg. when I continued after hitting that breakpoint it exited fine.

E: oh we do hook PeekMessageA / PeekMessageW to call into handle_window_message, guess those might get called just after it does destructor stuff.

Not really sure what an easy way to fix that might be, maybe could add some field to input class that gets set when inited & unset when destructed, and check that in our PeekMessage hooks, but not sure if that would run before or after s_windows dtor... if s_windows could be moved into the input class I guess something like that might work though?

albertre4HD commented 1 year ago

I've been having constant but inconsistent issues during the last years when leaving the Movie Browser, too. 5% of the times the game crashed. The amount of times this issue happens since I'm using re4_tweaks has been lower (maybe a coincidence ¿?.. no idea), and since anybody else mentioned this issue never, I always thought it was a problem with my computer and this game (you know... this game is poorly optimized) and never reported the problem. I'll try to force the crash and send the dump, just in case it helps

emoose commented 1 year ago

Been looking into the crash-on-exit, tried a few different ways:

That unhook-on-destruct method seems to work, was able to stop the crash by calling Hook::UnHotPatchAll(), but that would also unhook some things we hooked in KeyboardMouseTweaks.cpp... Tried to call Hook::UnhookHotPatch on each Win32 func we hooked separately, but that ran into a bunch of issues: UnhookHotPatch calls spd::log which causes exception because I guess it was already destructed, and unhooking RegisterRawInputDevices / ClipCursor seems to fail entirely with that func, maybe something else is hooking them after us?

That's probably the best way to try fixing it though, since the issue is really with the Win32 funcs that we hooked still being called after our destructors have ran, just not really sure what the best way to try unhooking them is.

I guess as last-ditch effort we could just make the destructor set some bool and then check that inside each of the hooks, kinda hacky way to do it though, but maybe easier than trying to unhook everything...

(also after fixing the crash via Hook::UnHotPatchAll() it seems the multithread-fix g_D3DMutex also has some issue with being used after destruction, guess that might also need some things unhooked :/)