Hard crach after exit on VM crash (4.7.0 - 4.8.2)

Bugs that have been investigated and resolved somehow.

Moderator: GZDoom Developers

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
User avatar
Apeirogon
Posts: 1603
Joined: Mon Jun 12, 2017 12:57 am

Hard crach after exit on VM crash (4.7.0 - 4.8.2)

Post by Apeirogon »

Multiple ternary operations in a row that have multiple checks inside of each, a la ( (condition && condition && condition) ? something : something), causes firstly vm crash with error message "DestroyAllThinkers failed" and than, on exit from Gzdoom, hard crash with a very dead marine.

Reproducing steps
1. drop attached archive on gzdoom
2. start new game
3. type into console 'netevent cube'
4. after vm crash type "exit" into console to trigger actual crash with crash report window

To prevent crash open archive/volume_filling/graph_storage.zc and comment lines 18-23.

Edit: its out of array bounds bug. Gzdoom just wont stops on first out of bounds write and continue doing it until it hit the end of a loop inside of which it was called.
You do not have the required permissions to view the files attached to this post.
Last edited by Apeirogon on Tue Aug 30, 2022 6:38 am, edited 2 times in total.
User avatar
Player701
 
 
Posts: 1473
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Location: Russia

Re: Multiple ternary with multiple checks crash (4.7.0 - 4.8.2)

Post by Player701 »

I doubt this has anything to do with the ternary operator at all. The crash happens in volume_filling/cube_node.zc at line 141, which is inside an OnDestroy() override, and the error says "tried to write to address zero". This likely indicates that there's a bug in the ZScript code. It's hard to tell without a deeper analysis, but I suppose that by commenting out the mentioned lines in volume_filling/graph_storage.zc the behavior of the code changes so that the bug is not triggered anymore. Nevertheless, the hard crash should probably not happen.

If you still think this is somehow related to the ternary operator, please provide a more concise example.
User avatar
Apeirogon
Posts: 1603
Joined: Mon Jun 12, 2017 12:57 am

Re: Multiple ternary with multiple checks crash (4.7.0 - 4.8.2)

Post by Apeirogon »

Yes, its not a ternary operation, its out of array bounds bug. Commenting aforementioned 6 lines also comment array access functions, since condition and array access related function are in one line.

What is weird here is that instead of crashing after first out of bounds write, like it always doing in all cases, gzdoom continues to write into an array until it hit end of a loop, inside of which writing is happens, and only than crashes.
User avatar
Apeirogon
Posts: 1603
Joined: Mon Jun 12, 2017 12:57 am

Re: Multiple 'out of array bounds' bug (4.7.0 - 4.8.2)

Post by Apeirogon »

Found a reason.
Overridden ondestroy virtual have leftover code from previous revision that writes pointer without checking is it null or not. So it goes like
  1. Gzdoom executes 'out of array bounds' bug
  2. crashes
  3. tries to destroy loaded level and all related to it data
  4. enters into overridden destructor
  5. writes to address zero
  6. print "write to address zero" message into console
  7. goto 3
However, I cant replicate hard crash on exit with dead marine window in this way.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48376
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Hard crach after exit on VM crash (4.7.0 - 4.8.2)

Post by Graf Zahl »

There's not really much that can be done about it. C++ actually has the same limitation that any exception thrown from a destructor will result in a hard abort.
User avatar
Apeirogon
Posts: 1603
Joined: Mon Jun 12, 2017 12:57 am

Re: Hard crach after exit on VM crash (4.7.0 - 4.8.2)

Post by Apeirogon »

Well, exception from destructor if there are already some exception happened, lead to instant termination of a program, but that not the point and not entirely what I meant.

Just to be clear, this

Code: Select all

version "3.8"

const MAX_SIZE = 6;
class thing : thinker
{
    pointer others[MAX_SIZE];

    static thing constructor()
    {
        let t = new("thing");
        t.others[0] = new("pointer");
        t.others[1] = new("pointer");
        t.others[2] = new("pointer");
        t.others[3] = new("pointer");
        t.others[4] = new("pointer");
        t.others[5] = new("pointer");
        return t;
    }

    override void ondestroy()
    {
        for(int i = 0; i < MAX_SIZE; i++)
        {
            if(others[i])
            {
                console.printf("OH NO");
                others[i].p.others[i] = null;

            }
        }
        super.ondestroy();
    }

    void out_of_bound_write(int a, thing t)
    {
        others[a].p = t;
    }
}

class pointer
{
    thing p;
}


class debug_build : eventhandler
{
    override void NetworkProcess (ConsoleEvent e) 
    {
        if(e.name == "bug")
        {
            array<thing> t; t.clear();
            
            t.push(thing.constructor() );
            t.push(thing.constructor() );
    
            t[0].out_of_bound_write(MAX_SIZE, t[1]);
        }
    }
}
will crash and flood console with "oops, cant destroy thinker" messages...which is expected. Stack unwinding, exception bytes and other scary words.
HOWEVER, if you relaunch game from main menu or switch map with CCMD, without relaunching Gzdoom, it would work fine.

Archive in first post after crashing VM also crashes Gzdoom if you try launching a new game, which should not happens.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48376
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Hard crach after exit on VM crash (4.7.0 - 4.8.2)

Post by Graf Zahl »

Like I said, it's impossible to avoid the crash here - this happens inside the cleanup operation of another exception.
What I did was to avoid running the garbage collector here, and if I receive another exception then, do a fatal error abort. That will give you a meaningful message, but once you dismiss that it'll still crash because, like I said, having a crash in a destructor (which onDestroy essentially is) is something that cannot be handled gracefully while cleaning up.

Return to “Closed Bugs [GZDoom]”