January 19, 2022

On Sunday, 16 January 2022 at 18:03:53 UTC, Paul Backus wrote:

>

On Sunday, 16 January 2022 at 15:15:07 UTC, Hipreme wrote:

>

Is there some way to throw a stack trace when killing the program from the CTRL+C from the terminal?

It would help a lot into debugging occasional infinity loops

On POSIX, you can use the sigaction function to install a signal handler for SIGINT, the signal generated by CTRL+C. To terminate the program with a stack trace, simply have the signal handler throw an Error.

Here's an example program that demonstrates the technique:

import core.sys.posix.signal;

extern(C) void handleCtrlC(int)
{
	throw new Error("Killed by CTRL+C");
}

void main()
{
	sigaction_t act = { sa_handler: &handleCtrlC };
	int errcode = sigaction(SIGINT, &act, null);

	f(); // call some functions
}

void f() { g(); }

void g() { h(); }

void h()
{
	while (1) {} // wait for ctrl+c
}

Make sure to compile with the -g option if you want your stack trace to have filenames and line numbers.

import std.stdio;

version(Posix)
{
    import core.sys.posix.signal;
    extern(C) void handleCtrlC(int)
    {
        throw new Error("Killed by CTRL+C");
    }

    bool setupSignal()
    {
        sigaction_t act = {sa_handler: &handleCtrlC};
        int errCode = sigaction(SIGINT, &act, null);
        return errCode == 0;
    }
}
else version(Windows)
{
    import core.sys.windows.windef;
    import core.sys.windows.wincon;
    extern(Windows) BOOL handleCtrlC(DWORD dwType)
    {
        switch(dwType)
        {
            case CTRL_C_EVENT:
                throw new Error("Killed by CTRL+C");
                break;
            case CTRL_BREAK_EVENT:
                throw new Error("Killed by break");
                break;
            default:
                throw new Error("Killed by unknown event");
                break;
        }
        return TRUE;
    }
    bool setupSignal()
    {
        return SetConsoleCtrlHandler(cast(PHANDLER_ROUTINE)&handleCtrlC, TRUE) == TRUE;
    }
}
else{bool setupSignal(){return false;}}

void a(){b();}
void b(){c();}
void c(){for(;;){}}

void main(string[] args)
{
    if(!setupSignal)
        writeln("Could not setup signal, exiting.");
    else
        a();
}

This is my current solution. The problem is that on Windows, it actually has the stack trace:

0x76909A63 in CtrlRoutine                                                                                               0x76BD6359 in BaseThreadInitThunk                                                                                       0x76FF7B74 in RtlGetAppContainerNamedObjectPath                                                                         0x76FF7B44 in RtlGetAppContainerNamedObjectPath

If I throw that error on the Ctrl, it actually shows a message box:

The exception unknown software exception (0xe04400001) occurred in the application at location: ...

Maybe there is some specific formatting for throwing exceptions to Windows recognize it?

1 2
Next ›   Last »