BetterC + Windows + setjmp longjmp
Lobachevsky
ibeam2000 at gmail.com
Wed May 22 16:37:36 UTC 2019
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;
}
More information about the Digitalmars-d-learn
mailing list