On Monday 01 June 2026 15:57:41 LIU Hao wrote: > 在 2026-5-31 20:32, Pali Rohár 写道: > > Hello, in attachment I'm sending larger patch series which fixes > > handling and processing of SEH exceptions at different levels. > > > > > diff --git a/mingw-w64-headers/include/ntdef.h > > b/mingw-w64-headers/include/ntdef.h > > index e8470243669d..f083abd1a9a2 100644 > > --- a/mingw-w64-headers/include/ntdef.h > > +++ b/mingw-w64-headers/include/ntdef.h > > @@ -723,7 +723,7 @@ struct _EXCEPTION_RECORD; > > #ifndef __PEXCEPTION_ROUTINE_DEFINED > > #define __PEXCEPTION_ROUTINE_DEFINED > > typedef EXCEPTION_DISPOSITION > > -(NTAPI *PEXCEPTION_ROUTINE)( > > +(__cdecl *PEXCEPTION_ROUTINE)( > > struct _EXCEPTION_RECORD *ExceptionRecord, > > PVOID EstablisherFrame, > > struct _CONTEXT *ContextRecord, > I think I mentioned this one before; this is not the same type as > `_except_handler`, and it's really __stdcall on x86-32. A handler on x86-32 > can be declared in either calling convention.
I'm not fully sure about this as I information which I found on archived MS web and also in other resources which comes prior introduction of amd64 shows that handler is (or was?) cdecl. Anyway, I mentioned it also in the commit message, even mingw-w64 header files have different definitions of that handler (some are cdecl, some are stdcall and some are without any keyword). So this is something which would be aligned to the one calling convention. If the handler can be declared in either calling convention then it should mean that caller of that handler needs to preserve %esp register (by copying it into %ebp addressed stack or into %ebx, %esi or %edi reg) before pushing arguments on stack and restore it after handler returns. That is because the caller of handler cannot know calling convention and whether handler pops the stack or not. At least this is my theory how it could work if handler can be really either cdecl or stdcall. It is somewhere documented? > > > + /* Pre-Win2k systems do not have to enable CR4.OSFXSR and then > > + * SSE instructions cannot be used even when CPU has SSE support. > > + * So these systems has to be marked as without SSE support. > > + * Try to execute SSE nop "xorps %%xmm0, %%xmm0" and check if system > > This is not a nop; it sets XMM0 to zero. A correct nop instruction is `movaps > xmm0, xmm0`. That is stupid mistake. Just for explanation: Originally I wrote xor and marked xmm0 as scratch reg for inline asm. Then I realized that mov is better as it is a real nop and no scratch reg is needed. So modified the code and comment, removed scratch reg... and forgot to change instruction. > > > From 81d393f64e395222d2c26bfcaccdecaf2c9c5641 Mon Sep 17 00:00:00 2001 > > From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]> > > Date: Thu, 14 May 2026 21:30:50 +0200 > > Subject: [PATCH 10/29] crt: Implement POSIX sigsetjmp and siglongjmp > > functions > > > > For jumping out of the signal handler and recovering the application it is > > needed to use sigsetjmp and siglongjmp functions instead of setjmp and > > longjmp functions. > > > > One thing you should note is that the handler for SIGINT runs on its own > thread: > > #include <windows.h> > #include <stdio.h> > #include <signal.h> > > volatile sig_atomic_t handler_tid = 0; > > void > ctrl_c_handler(int sig) > { > handler_tid = GetCurrentThreadId(); > } > > int > main(void) > { > signal(SIGINT, ctrl_c_handler); > fprintf(stderr, "sleeping for 5 seconds\n"); > Sleep(5000); > fprintf(stderr, "resuming\n"); > > fprintf(stderr, "main tid = %d\n", (int) GetCurrentThreadId()); > fprintf(stderr, "handler tid = %d\n", (int) handler_tid); > } > > > This can give (of course you will need to press Ctrl+C once before > 'resuming'): > > sleeping for 5 seconds > resuming > main tid = 4144 > handler tid = 20976 > > > If `siglongjmp()` is called in such a handler, it will jump to another > thread. This doesn't seem POSIX-compliant anyway, so I'm dropping this patch > for now. Ok, this is really bad. Is C even allowing to run signal handler in different thread than the which one triggered it? sigsetjmp/siglongjmp functions are needed by that SIGFPE test. I see that there is a proposal to rename those functions with mingw prefix. Another possible option could be to not introduce these functions at all into mingwex library, but instead put implementation of them as static non-exported functions into the SIGFPE test itself. What do you prefer more? If there is such issue with SIGINT, I'm not really sure if it is a good idea to have such function (even prefixed by __mingw) exported for all applications. So I slightly prefer to have them in the test code. > > > #if defined(__i386__) > > __writefsdword (0, (DWORD)exception_record.Next); /* unregister SEH > > handler */ > > +#elif defined(SEH_INLINE_ASM) > > + asm volatile ("nop"); /* needed for GAS to generate SEH handler > > correctly */ > > Why the nop was needed? It's because if an exception happens inside a call > `__C_specific_handler` looks at the return address of that call, which must > have been pushed onto the stack, so > > // scope begins > ... > call foo > nop // ** RIP points here > // scope ends > > If there wasn't the nop in this case, the return address would have equaled > the end of scope, and would not have been covered by the handler. > > `.seh_handler` is not subject to such an issue. This change is needed just for one or two intermediate commits. Is the extending the description for that intermediate commit needed? _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
