I have been experimenting with setjmp / longjmp under Windows as a way to break out of an endless loop. With my experiments, longjmp appears to silently exit the process, no stack trace, nothing. Black emptiness.

I stared with the C program described in

https://docs.microsoft.com/en-us/windows/console/setconsolectrlhandler

and added the setjmp and longjmp code fragments.

When I try this, the CtrlHandler is successfully loaded and it even beeps accordingly when cntl-C and cntl-break are pressed. Of course, the Microsoft documentation warns against using setjmp / longjump from callbacks:

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/longjmp?view=vs-2019

Here is the companion Microsoft setjmp documentation:

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setjmp?view=vs-2019

I'm using DMD 2.084, VS 2017, not using BetterC
Compiler arguments: -boundscheck=on -dw -c -gf -debug -g -m64 -wi
Linker: /OUT:"C:\Users\...\Test.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Users\...\Test.pdb" /DEBUG /MACHINE:X64 /INCREMENTAL /PGD:"C:\Users\...\Test.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Testexe.intermediate.manifest" /ERRORREPORT:PROMPT /VERBOSE:Lib /TLBID:1

Suggestions welcome.

----------------------------------------------------------------------------

// CtrlHandler.d : This file contains the 'main' function. Program execution begins and ends there. // See https://docs.microsoft.com/en-us/windows/console/setconsolectrlhandler

module CtrlHandler;
import core.sys.posix.setjmp;
import std.conv;
import core.sys.windows.windows;
import std.stdio;
// #include <windows.h>
// #include <stdio.h>

        alias ubyte[1024] jmp_buf;

        extern(C) {
                int _setjmp(ref jmp_buf) nothrow;
                void longjmp(ref jmp_buf, int) nothrow;
        }

        alias _setjmp setjmp;

        public static jmp_buf buf;

extern (Windows) private static int CtrlHandler(uint fdwCtrlType) nothrow {

                switch (fdwCtrlType) {

                        // Handle the CTRL-C signal.
                        case CTRL_C_EVENT:
                                // writeln("Ctrl-C event\n\n");
                                Beep(750, 300);
                                longjmp(buf, 42);
                                break;

                        // CTRL-CLOSE: confirm that the user wants to exit.
                        case CTRL_CLOSE_EVENT:
                                Beep(600, 200);
                                // writeln("Ctrl-Close event\n\n");
                                longjmp(buf, 39);
                                break;

                        // Pass other signals to the next handler.
                        case CTRL_BREAK_EVENT:
                                Beep(900, 200);
                                // writeln("Ctrl-Break event\n\n");
                                longjmp(buf, 13);
                                break;

                        case CTRL_LOGOFF_EVENT:
                                Beep(1000, 200);
                                // writeln("Ctrl-Logoff event\n\n");
                                return 0;

                        case CTRL_SHUTDOWN_EVENT:
                                Beep(750, 500);
                                // writeln("Ctrl-Shutdown event\n\n");
                                return 0;

                        default:
                                return 0;
                }
                return 0;
        }

        int main(string[] args)
        {
                int sj;
                sj = setjmp(buf);
                writeln("sj = " ~ to!string(sj));
                readln();
                if (sj != 0) goto breakout;

                if (SetConsoleCtrlHandler(&CtrlHandler, 1))
                {
                        writeln("\nThe Control Handler is installed.\n");
                        writeln("\n -- Now try pressing Ctrl+C or Ctrl+Break, 
or");
                        writeln("\n    try logging off or closing the 
console...\n");
                        writeln("\n(...waiting in a loop for events...)\n\n");

                        while (1) {}
                }
                else
                {
                        writeln("\nERROR: Could not set control handler");
                        return 1;
                }

        breakout:
writeln("\nSuccessfully broke out of endless loop - sj = " ~ to!string(sj));
                return 0;
        }




Reply via email to