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