September 19, 2018
On Wednesday, 19 September 2018 at 11:12:41 UTC, Diederik de Groot wrote:
> On Wednesday, 19 September 2018 at 11:06:23 UTC, Diederik de Groot wrote:
>> On Tuesday, 18 September 2018 at 19:45:18 UTC, SrMordred wrote:
>
>> Only the exact size of the jmp_buf is important (not the details about the content). We only call a function with it, we never look inside.
>
> I don't own any windows machines so had to use these references (and could not test anything):
> - WinSDK10: goo.gl/m9DjZt
> - MARS: goo.gl/Qoc6g2
> Code above does not yet cover the Mars case, but the i386 sizes should be the same.
> Please Note: setjmp/longjmp should only be used in "@system + @nogc + nothrow / -betterC" code.

g++ and clang give me sizeof = 256. dmc give me 64. I tried all this sizes and other, but still crashes.
September 20, 2018
Ok, after a better look at the sources I finally got it:

setjmp is a macro.
the true function signature is "int _setjmp(jmp_buf, void*)"

the void* is the current function address which in mingw sources are capture by "__builtin_frame_address(0)".

And I did´t look yet to see if Dlang have an equivalent.
but calling _setjmp(jmp_buf, null); the simple examples are working :)
September 20, 2018
On Thursday, 20 September 2018 at 12:11:55 UTC, SrMordred wrote:
> Ok, after a better look at the sources I finally got it:
>
> setjmp is a macro.
> the true function signature is "int _setjmp(jmp_buf, void*)"
>
> the void* is the current function address which in mingw sources are capture by "__builtin_frame_address(0)".
>
> And I did´t look yet to see if Dlang have an equivalent.
> but calling _setjmp(jmp_buf, null); the simple examples are working :)

Nice to see you managed to figure it all out, congrats!

So it now looks something like this ?:

version(Windows) {
  version(X86)
    enum _JBLEN = 64;
  else version(X86_64)
    enum _JBLEN = 256;
  else version(IA64)
    enum _JBLEN = 528;
  alias ubyte[_JBLEN] jmp_buf;

  extern (C) {
    int  _setjmp(ref jmp_buf, null);
    void longjmp(ref jmp_buf, int);
  }
  alias _setjmp setjmp;
}

Hopefully you will be able to merge the two examples and create a nice druntime PR out of it. The https://forum.dlang.org/post/mmxwhdypncaeikknlpyq@forum.dlang.org version does look a lot cleaner (but also a little more cryptic).
Might be wise to follow the core.sys.posix.setjmp.d implementation. If available, maybe also add the sigsetjmp / siglonggmp and sigaction versions (if available on windows).

Good luck !

May 22, 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;
	}




May 22, 2019
On Wednesday, 22 May 2019 at 16:37:36 UTC, Lobachevsky wrote:
> 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 don't think breaking out of a loop this way can work. The CtrlHandler is called by another thread. Quoting from https://docs.microsoft.com/en-us/windows/console/handlerroutine:

> An application-defined function used with the SetConsoleCtrlHandler function. A console process uses this function to handle control signals received by the process. When the signal is received, the system creates a new thread in the process to execute the function.
1 2
Next ›   Last »