Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Blue-Shift] Crash on save at ba_outro. #1014

Open
x414e opened this issue Apr 13, 2013 · 1 comment
Open

[Blue-Shift] Crash on save at ba_outro. #1014

x414e opened this issue Apr 13, 2013 · 1 comment

Comments

@x414e
Copy link

x414e commented Apr 13, 2013

After you pass through the portal at the very end of the game, if you attempt to save (quicksave or manual) the game at certain areas such as xen or during a black/green screen or credits it will just crash and drop to desktop.

I am using Linux Mint 14.

@SamVanheer
Copy link

SamVanheer commented May 5, 2019

Confirmed to still happen in the current public version.

Backtrace:

Thread 1 "hl_linux" received signal SIGSEGV, Segmentation fault.
0xaefb58d0 in EHANDLE::Get (this=0x9709f0c) at ../blueshift/dlls/cbase.cpp:446
446	../blueshift/dlls/cbase.cpp: No such file or directory.
(gdb) bt
#0  0xaefb58d0 in EHANDLE::Get (this=0x9709f0c)
    at ../blueshift/dlls/cbase.cpp:446
#1  EHANDLE::operator CBaseEntity* (this=0x9709f0c)
    at ../blueshift/dlls/cbase.cpp:465
#2  0xaf059038 in CSave::WriteFields (this=0xbfffdecc, 
    pname=0xaf08e577 "CTriggerPlayerFreeze", pBaseData=0x9709ea0, 
    pFields=0xaf0c3e40 <CTriggerPlayerFreeze::m_SaveData>, fieldCount=1)
    at ../blueshift/dlls/util.cpp:2106
#3  0xaf0493ac in CTriggerPlayerFreeze::Save (save=..., this=0x9709ea0)
    at ../blueshift/dlls/triggers.cpp:2460
#4  CTriggerPlayerFreeze::Save (this=0x9709ea0, save=...)
    at ../blueshift/dlls/triggers.cpp:2456
#5  0xaefb483c in DispatchSave (pent=0xabeae3e4, pSaveData=0xa1314f8)
    at ../blueshift/dlls/cbase.cpp:278
#6  0xb6782dff in SaveGamestate () at ../engine/host_cmd.c:2539
#7  0xb67843bd in SaveGameSlot (pSaveName=0xabb83dd0 "quick", 
    pSaveComment=0xbfffe620 "#BA_OUTRO", ' ' <repeats 56 times>, "00:20")
    at ../engine/host_cmd.c:2068
#8  0xb6784dbd in Host_Savegame_f () at ../engine/host_cmd.c:2194
#9  Host_Savegame_f () at ../engine/host_cmd.c:2164
#10 0xb6765c0e in Cmd_ExecuteStringWithPrivilegeCheck (
    text=0xbfffe730 "save quick", bIsPrivileged=<optimized out>, 
    src=<optimized out>) at ../engine/cmd.c:1196
---Type <return> to continue, or q <return> to quit---
#11 0xb6765e4d in Cmd_ExecuteStringWithPrivilegeCheck (bIsPrivileged=true, 
    src=src_command, text=0xbfffe730 "save quick") at ../engine/cmd.c:1155
#12 Cbuf_ExecuteFromBuffer (buf=0xb6fccaf0 <cmd_text>, bIsPrivileged=true)
    at ../engine/cmd.c:244
#13 0xb6765e72 in Cbuf_Execute () at ../engine/cmd.c:262
#14 0xb677d093 in _Host_Frame (time=0.0743620619) at ../engine/host.c:1384
#15 0xb677d542 in Host_Frame (time=0.0743620619, iState=1, 
    stateInfo=0xbfffec5c) at ../engine/host.c:1522
#16 0xb67a9e64 in CEngine::Frame (this=0xb69c2a20 <g_Engine>)
    at ../engine/sys_engine.cpp:245
#17 0xb67a78f3 in RunListenServer (instance=0x0, 
    basedir=0x804b220 <szBaseDir> "/home/sam/.local/share/Steam/steamapps/common/Half-Life", 
    cmdline=0x80533c0 "/home/sam/.local/share/Steam/steamapps/common/Half-Life/hl_linux -game bshift +sv_cheats 1", 
    postRestartCmdLineArgs=0x804d360 <main::szNewCommandParams> "", 
    launcherFactory=0x8049350 <CreateInterfaceLocal(char const*, int*)>, 
    filesystemFactory=0xb79e6d40 <CreateInterface(char const*, int*)>)
    at ../engine/sys_dll2.cpp:946
#18 0x08048d67 in main (argc=5, argv=0xbfffee94)
    at ../launcher/launcher.cpp:439

The trigger_playerfreeze entity class looks like this:

CTriggerPlayerFreeze : CBaseDelay
{
  bool m_bUnFrozen;
};

Reverse engineering the entity reveals the problem:

TYPEDESCRIPTION CTriggerPlayerFreeze::m_SaveData[1]
_ZN20CTriggerPlayerFreeze10m_SaveDataE TYPEDESCRIPTION <FIELD_EHANDLE, offset aM_bunfrozen, 6Ch, 1, 0>

The m_bUnFrozen variable is save/restored as an EHANDLE, so it tries to save off the entity id and accesses invalid memory.

Note that using FIELD_BOOLEAN is not enough to fix this. That's intended for the 4 byte BOOL type, change the type of the variable to BOOL so it will work properly.

Opposing Force has the same entity but does not save/restore this field. It happens to work properly because the player's frozen state is separately saved and restored, and m_bUnFrozen is set to false while the player is frozen. When the game restores the entity the memory for it is zero initialized so it will still be valid despite not restoring correctly.

I suspect this is why the variable tracks whether the player is unfrozen, rather than frozen. They may have encountered the bug during development and patched it by inverting the meaning of the boolean.

Note that any changes to save data will break old saved games.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants