There's a problem when I use longjmp in a 32-bit application on Windows 64-bit (Windows 7). Instead of returning to a point of the last setjmp() call, it lands after the last DispatchMessage() call. Here's the code example, which works fine if compiled by a 64-bit compiler, and fails with a 32-bit version.
Are there any ideas for a workaround? Microsoft seems to be silent on a tangential question here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/b63a573f-007e-43a3-877c-b06280aa8bcc/0x80000026-application-error-when-exiting-after-using-longjmp-on-windows8-x64?forum=windowscompatibility
// Compile as: cl a.c user32.lib kernel32.lib
#include <windows.h>
#include <setjmp.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
jmp_buf jump_buffer;
int flag = 0;
int main()
{
WNDCLASS wc = {0, };
ATOM atom = 0;
HWND wnd;
MSG msg;
int ret;
wc.lpfnWndProc = &WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "ExitWindows() handler";
atom = RegisterClass(&wc);
wnd = CreateWindow(wc.lpszClassName, wc.lpszClassName,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wc.hInstance, NULL);
ret = setjmp(jump_buffer);
switch ( ret ) {
case 0:
ShowWindow(wnd,SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if ( flag ) {
printf("not ok\n");
break;
}
}
break;
case 1:
printf("ok\n");
break;
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_PAINT:
flag = 1;
longjmp(jump_buffer, 1);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
Using longjmp
in WndProc is unsafe because of the nature of a window procedure:
SendMessage
function, in which case it in not called with the same context (stack) that what you used for the setjmp
. In that case, I think that anything could happen... - Ok WM_PAINT in normally posted and not sent so that should not apply here, even if IMHO it is the main reason to not do thatThe Windows API on WindowProc functions says: The return value is the result of the message processing and depends on the message sent.
My understanding of it is that a window procedure is supposed to return and to never call longjmp
of exit
. It is not explicit in Windows documentation, but I would not dare use a window procedure that would not return.
The correct way to exit correctly from a message loop is by posting a WM_QUIT message (Use the PostQuitMessage function to exit a message loop). It makes the GetMessage
functions returns 0 and allows the system to cleanup the message loop that was installed at first call to GetMessage
.
User contributions licensed under CC BY-SA 3.0