Tk Source Code

View Ticket
Login
2025-12-03
16:42 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Closed with 5 other changes artifact: f9f6d242 user: jan.nijtmans
16:26 • Ticket [44b34c61]: 6 changes artifact: 505d45ae user: oehhar
14:29 • Closed ticket [44b34c61]. artifact: fadf12a9 user: jan.nijtmans
2025-11-27
20:27 • Ticket [44b34c61]: 3 changes artifact: e78c1308 user: jan.nijtmans
19:43 • Ticket [44b34c61]: 3 changes artifact: a813546e user: oscarfv
19:18 • Ticket [44b34c61]: 3 changes artifact: 597a9c56 user: dkf
19:08 • Ticket [44b34c61]: 3 changes artifact: 461edec7 user: dkf
2025-11-24
10:48 • Ticket [44b34c61]: 3 changes artifact: 5990d617 user: oscarfv
09:43
Remove all SEH error-handling for TkFinalize. See [44b34c6152] check-in: 71ee5f9d user: jan.nijtmans tags: trunk, main
09:16
(backport): Don't protect TkFinalize() with SEH on arm64 and in debug more. See [44b34c6152] check-in: a4d1080c user: jan.nijtmans tags: core-9-0-branch
09:10 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Open with 3 other changes artifact: f4cc45bf user: jan.nijtmans
09:03 • Ticket [44b34c61]: 3 changes artifact: ff2a6f84 user: jan.nijtmans
2025-11-17
16:07 • Ticket [44b34c61]: 3 changes artifact: 2bb22b97 user: oscarfv
16:03 • Ticket [44b34c61]: 3 changes artifact: fc87a675 user: jan.nijtmans
15:36 • Ticket [44b34c61]: 4 changes artifact: bc5bec06 user: oehhar
14:26 • Ticket [44b34c61]: 3 changes artifact: 01630fb3 user: oscarfv
14:21 • Ticket [44b34c61]: 3 changes artifact: e162fcca user: oscarfv
13:19 • Ticket [44b34c61]: 3 changes artifact: cf137db3 user: jan.nijtmans
13:17
Don't protect TkFinalize() with SEH on arm64 and in debug more. See [44b34c6152] check-in: df7d241d user: jan.nijtmans tags: trunk, main
13:12 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Open with 3 other changes artifact: 0a6a0ae2 user: jan.nijtmans
13:03 • Ticket [44b34c61]: 3 changes artifact: 6d69bb46 user: oscarfv
2025-11-12
17:56
Fix [44b34c6152]: Fix crash on exit due to faulty asm code in DllMain check-in: 56313c32 user: jan.nijtmans tags: core-8-6-branch
15:24 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Open with 3 other changes artifact: 3b83411e user: oscarfv
14:38 • Ticket [44b34c61]: 3 changes artifact: 395ed64a user: jan.nijtmans
13:18
Fix [44b34c6152]: Fix crash on exit due to faulty asm code in DllMain check-in: f13be8dc user: jan.nijtmans tags: core-9-0-branch, core-9-0-3-rc, core-9-0-3
12:53 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Open with 3 other changes artifact: 8c15eb4f user: oscarfv
11:30 • Ticket [44b34c61]: 3 changes artifact: 83a286a8 user: jan.nijtmans
10:40 • Ticket [44b34c61]: 3 changes artifact: ce28512f user: oscarfv
10:03 • Open ticket [44b34c61]. artifact: 2ca60378 user: jan.nijtmans
2025-11-11
18:44 • Ticket [44b34c61]: 4 changes artifact: c8f7f5c0 user: oscarfv
16:11 • Ticket [44b34c61]: 5 changes artifact: e80c8d38 user: oscarfv
15:25 • Ticket [44b34c61]: 4 changes artifact: 5f389073 user: jan.nijtmans
15:23
Fix [44b34c6152]: Fix crash on exit due to faulty asm code in DllMain check-in: b07bae01 user: jan.nijtmans tags: core-8-6-branch
15:11 • Closed ticket [44b34c61]: Fix crash on exit due to faulty asm code in DllMain plus 6 other changes artifact: 2db6b4d3 user: jan.nijtmans
15:08
Fix [44b34c6152]: Fix crash on exit due to faulty asm code in DllMain check-in: 9b98d74b user: jan.nijtmans tags: bug-44b34c6152
2025-11-10
12:31 • Ticket [44b34c61] Fix crash on exit due to faulty asm code in DllMain status still Open with 3 other changes artifact: d311a79b user: oscarfv
2025-11-07
22:01 • Ticket [44b34c61]: 4 changes artifact: a41a52d0 user: jan.nijtmans
21:17 • Ticket [44b34c61]: 3 changes artifact: 0db781bc user: oscarfv
21:03 • New ticket [44b34c61]. artifact: 16d77275 user: oscarfv

Ticket UUID: 44b34c61529e5cedae54e204da71af4fcfcbab5b
Title: Fix crash on exit due to faulty asm code in DllMain
Type: Patch Version:
Submitter: oscarfv Created on: 2025-11-07 21:03:39
Subsystem: 99. Other Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2025-12-03 16:42:38
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2025-12-03 16:42:38
Description:
Building tk with a recent gcc version (>= 15) on mingw64 with -fstack-protector-strong -O2 causes a crash on exit. For reproducing, just execute wish and exit.

The problem is the assembler code in win/tkWin32Dll.c DllMain.

The call to TkFinalize via assembler causes all non-caller-saved registers to be potentially clobbered, but the clobber list of the __asm__ block does not mention them all (currently they are quite a few and the list grows as new registers are introduced by extensions such as AVX*, etc.)

When compiling with the options mentioned above, the compiler introduces extra code for checking against stack smashing and that uses some of the registers clobbered by the assembler call to TkFinalize.

Please note that any other change to DllMain (in source code or build options) might introduce this problem as well.

We could add all non-caller-saved registers to the list, but the most robust, future-proof approach is to not call TkFinalize from assembler, letting the compiler figure out register handling. The patch below splits the assembler code in two chunks surrounding the C call to TkFinalize. It also adjusts the list of clobbered registers to reflect those that are actually modified by the corresponding assembler block.

diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c
index 5161333da..fd15e5206 100644
--- a/win/tkWin32Dll.c
+++ b/win/tkWin32Dll.c
@@ -148,13 +148,21 @@ DllMain(
 
 	    "movq	%%rdx,		%%gs:0"		"\n\t"
 
-	    /*
-	     * Call TkFinalize
-	     */
+	    :
+	    /* No outputs */
+	    :
+	    [registration]	"m"	(registration),
+	    [error]		"i"	(TCL_ERROR)
+	    :
+	    "%rax", "%rdx", "memory"
+	);
 
-	    "movq	$0x0,		0x0(%%rsp)"		"\n\t"
-	    "call	TkFinalize"			"\n\t"
+        /* Just do a regular C call so we don't need to worry about following
+         * the calling convention, specially the registers the function may
+         * clobber: */
+        TkFinalize(NULL);
 
+	__asm__ __volatile__ (
 	    /*
 	     * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION
 	     * and store a TCL_OK status
@@ -188,11 +196,9 @@ DllMain(
 	    :
 	    /* No outputs */
 	    :
-	    [registration]	"m"	(registration),
-	    [ok]		"i"	(TCL_OK),
-	    [error]		"i"	(TCL_ERROR)
+	    [ok]		"i"	(TCL_OK)
 	    :
-	    "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "memory"
+	    "%rax", "%rdx", "%rbp", "memory"
 	);
 
 #   else
@@ -218,12 +224,18 @@ DllMain(
 
 	    "movl	%%edx,		%%fs:0"		"\n\t"
 
-	    /*
-	     * Call TkFinalize
-	     */
+	    :
+	    /* No outputs */
+	    :
+	    [registration]	"m"	(registration),
+	    [error]		"i"	(TCL_ERROR)
+	    :
+	    "%eax", "%ebx", "%edx", "memory"
+	);
+
+        TkFinalize(NULL);
 
-	    "movl	$0x0,		0x0(%%esp)"		"\n\t"
-	    "call	_TkFinalize"			"\n\t"
+	__asm__ __volatile__ (
 
 	    /*
 	     * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION
@@ -259,11 +271,9 @@ DllMain(
 	    :
 	    /* No outputs */
 	    :
-	    [registration]	"m"	(registration),
-	    [ok]		"i"	(TCL_OK),
-	    [error]		"i"	(TCL_ERROR)
+	    [ok]		"i"	(TCL_OK)
 	    :
-	    "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
+	    "%eax", "%ebx", "%edx", "%ebp", "memory"
 	);
 
 #   endif
User Comments: jan.nijtmans added on 2025-12-03 16:42:38:

> What about back-porting to 9.0 and 8.6 ?

Is already done (the initial part only, not the removal of all SEH code)


oehhar added on 2025-12-03 16:26:58:

Great ! What about back-porting to 9.0 and 8.6 ? This sounds quite serious (crash)? THanks, Harald


jan.nijtmans added on 2025-12-03 14:29:48:

Closing, because the SEH code removal is in Tcl/Tk 9.1 now.

Please re-open if any new unexpected problem shows up. I'm quit confident that won't happen.


jan.nijtmans added on 2025-11-27 20:27:44:

> Those socket tests, do they load Tk? Is an exception thrown from TkFinalize? If yes, that would be very interesting by itself, see the discussion here.

Those socket failures are in Tcl only (without Tk), and they were there already before we made the SEH changes. So, this ticket - for sure - didn't cause it.


oscarfv added on 2025-11-27 19:43:46:
@dkf:

Please note that this ticket was reporting an "always crashing" scenario. See the original report.

The current asm split in two block was for fixing that crash. The only thing that can be objected wrt the previous code is that the first block references a label defined on the second block. I tested that the generated address is correct, but that was just one configuration.

For solving the label cross-reference we could use "asm goto". However, that doesn't make the general situation any better. The asm code does terrible things, like assigning the stack registers. Oh, and the call to TkFinalize on the previous version, for amd64, was writing the stack (not "push %0x0", but "movq $0x0, 0x0(%%rsp)" !) instead of passing the parameter on a register, as the ABI requires.

In general, you can't expect to balance the stack on the exception code path because you we don't know certain things that only the compiler knows.

Those socket tests, do they load Tk? Is an exception thrown from TkFinalize? If yes, that would be very interesting by itself, see the discussion here.

Finally, the SEH hacks in Tcl are superfluous, as the WIN API functions they wrap do not throw exceptions (unless, for one of then, when the program is running under a debugger, but then you don't want to hide those exceptions.)

dkf added on 2025-11-27 19:18:03:

OK, now I've looked at the code as it was in Tk, and yikes!

Unlike the instead-of-SEH code in Tcl, the code in Tk was split into several asm blocks around the call to TkFinalize(). Which appears to be the thing that one mustn't do. The Tk code needed to be improved for sure!

The conclusion that that extended to Tcl was not well-founded, as those were balancing the stack correctly. If this has been the cause of a bug I've been hunting this week with a crash in the guts of the socket tests, I will be quite upset. (For platforms such as ARM64, if the compiler doesn't have SEH then we can do without.)


dkf added on 2025-11-27 19:08:38:

The asm code was always a workaround; we would always have rather not have had it. The real question is whether there are systems that were using it; the asm in Tcl was always for x86 only. On ARM? It shouldn't have been used.

Didn't look at the situation in Tk yet though...


oscarfv added on 2025-11-24 10:48:20:
No objections, just me being annoyingly pedantic:

> This is high-risk: A long-lasting existing clean-up bug in user code could lead to an exception withthis change, which worked fine before.

Please note that Windows API functions don't throw exceptions (except a few of them when running in a debugger.)  Other sources of exceptions, such as divide-by-zero, are unlikely on this scenario. So the most probable cause for an exception in TkFinalize is an access violation (a.k.a. SIGSEGV) and that is anything but "working fine". As mentioned elsewhere, if those problems exist, we want to fix them.

Please CC me if you see reports related to this. Thank you.

jan.nijtmans added on 2025-11-24 09:10:47:

> My POV is that an exception in TkFinalize would be a bug on Tk and we should fix it

Not necessary: TkFinalize() also runs exit handlers, which could do anything. There could be a bug there causing an exception.

Still I agree with you: We are not responsible for user-inserted bugs, so - still - in that case we we would want to see the exception. This is high-risk: A long-lasting existing clean-up bug in user code could lead to an exception withthis change, which worked fine before. Therefore I intend to backport the partial fix to 9.0, and fully remove all SEH handlers in Tcl/Tk 9.1a1: then, if an issue is found during beta-testing (which I don't expect) we still can (partially) revert the change.

Any objections?


jan.nijtmans added on 2025-11-24 09:03:33:

Proposed [df7d241d4372112b|change] is in effect on trunk now. It looks like it works fine.


oscarfv added on 2025-11-17 16:07:56:
> The reason for this code is unknown.

What transpires from the bug report and the commit logs is that sometimes an exception was thrown from TkFinalize and, instead of investigating its cause and fixing it, the SEH handling code was added to hide the exception.

Maybe fixing the source of the exception was hard and the consequences of a half-done TkFinalize were considered as mild.

My POV is that an exception in TkFinalize would be a bug on Tk and we should fix it. Sadly, now we are on a scenario were there is a suspicion of something being wrong in TkFinalize but not observing the problem is no proof of its nonexistence.

I also think that SEH was used without fully understanding its implications. See the occurrences in Tcl, where they make no sense in two cases and very little sense on the third, as I mentioned on a previous comment. All those can be removed with confidence.

jan.nijtmans added on 2025-11-17 16:03:53:

> Although I'm afraid that that combination is not very frequently used

Well, let's clarify. It's not a combination, it's either one. So it involves Windows on _all_ ARM64 platforms, and also on all other platforms (x86 and x86_64) in debug mode.

As Harald pointed out, we want to remove it fully in Tcl 9.1a1. That way, if any problems show up, we can modify it again in Tcl 9.1a2, depending on the lessons learned.

So, thanks for your suggestion! You are being listened at ;-)


oehhar added on 2025-11-17 15:36:16:
We discussed it in the biweekly telco.

The reason for this code is unknown.
To find out, if full removal of SEH catch is ok, it was proposed to remove it and test in the alpha phase of Tk9.1.
It may be re-integrated if there are any issues in the field.

Harald

oscarfv added on 2025-11-17 14:26:08:
> A discussion about going even further is 

I think you left the phrase incomplete.

By the way, if there are reports about crashes on arm/windows/debug causud by the call to TkFinalize, I'll appreciate if you ping me. Although I'm afraid that that combination is not very frequently used.

oscarfv added on 2025-11-17 14:21:47:
Thanks!

jan.nijtmans added on 2025-11-17 13:19:06:

The follow-up proposal is here: https://core.tcl-lang.org/tk/timeline?r=bug-44b34c6152 It is just merged to trunk

At least in debug mode and on arm64 we won't use the SEH handler any more. A discussion about going even further is


jan.nijtmans added on 2025-11-17 13:12:41:

> Any objections to the revised patch posted on 2025-11-12 10:40:35 ?

No objections, therefore it was released with 9.0.3 already ;-)


oscarfv added on 2025-11-17 13:03:54:
Any objections to the revised patch posted on 2025-11-12 10:40:35 ? The only difference is that it removes rbp/ebp from the "clobbers" list.

oscarfv added on 2025-11-12 15:24:30:
I vill patch my development build to call TkFinalize without the SEH hack. Even causing SEH exceptions from within TkFinalize. To see what happens.

In the meantime, can you apply the revised patch that I posted a few hours ago? Let's try at least to not crash the application in the normal execution path :-)

jan.nijtmans added on 2025-11-12 14:38:07:

So, make steps on getting rid of it, in small steps.

The first step could be, call TkFinalize(NULL) on arm64 and in debug mode on x86. Let's see how far this brings us. At least programming errors in TkFinalize could be detected then.


oscarfv added on 2025-11-12 12:53:48:
> If an exception is thrown _inside_ TkFinalize, we don't want to stop it from doing further steps to unload the dll. The worst that could happen is a resource leak.

The worst that could happen is corrupting memory owned by the embedding application (which includes the stack.)

I embed Tcl/Tk in my applications. Some of them do delicate stuff. If TkFinalize crashes, for whatever reason, I *absolutely* want to know. My applications implement exception handling for bailing out on a specific way when an exception happens, differentiating by type of exception. This hack works against me.

Currently TkFinalize could be throwing exceptions more often than not due to a bug in Tk's code without we knowing about it.

Also, it is implemented on the proper way (__try ... __catch) for one platform, as a hack (__asm__) for some other platforms, and not implemented at all for the rest (which now is ARM.)

Finally, the way the __asm__ hack is implemented looks very fragile to me. I have doubts about how well it works in case an exception is thrown. It depends on many factors.

Looking into the history of this use of SEH, it begins here:

Date:   Sun Dec 21 23:50:13 2003 +0000
[...]
            * win/winMain.c:      DllMain's DLL_PROCESS_DETACH now protected with
                                  SEH as DeleteWindowsExitProc is causing an
                                  exception of its own under some teardown
                                  conditions.  AT&T assembly syntax has not been
                                  added for MinGW yet.  [Tcl Patch 858493]

Digging on the referenced patch:

https://sourceforge.net/p/tcl/patches/311/

it was motivated by a problem terminating Tk from a  __try ... __finally SEH handler. But gcc has no SEH, so why bother about faking it in DllMain at all?

The author expressed concerns similar to mine:

"I sure hope this won't mask
programming errors other developers might create in their
journeys of embedding."

jan.nijtmans added on 2025-11-12 11:30:02:

Thanks, let's see: [f3c74805]

> but I suggest to consider what I mentioned yesterday about the sanity of hiding exceptions from the embedding application

Understood, but I also kind of understand why this was done: If an exception is thrown _inside_ TkFinalize, we don't want to stop it from doing further steps to unload the dll. The worst that could happen is a resource leak. But most application which load Tk only unload Tk when the application ends.

That's why I'm reluctant to change that.


oscarfv added on 2025-11-12 10:40:35:
Ok, that's because the build uses %rbp/%ebp for the frame pointer and my patch added that register to the __asm__ clobbers section.

So for "fixing" this we need to remove %rbp/%ebp from the clobbers list, when actually it is written to on the __asm__ block, i.e. lie to the compiler. Another hint about how horrible this "fake SEH" hack is.

That's a trivial "fix" (see below), but I suggest to consider what I mentioned yesterday about the sanity of hiding exceptions from the embedding application.

Adapted patch:

diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c
index 5161333da..fd15e5206 100644
--- a/win/tkWin32Dll.c
+++ b/win/tkWin32Dll.c
@@ -148,13 +148,21 @@ DllMain(
 
 	    "movq	%%rdx,		%%gs:0"		"\n\t"
 
-	    /*
-	     * Call TkFinalize
-	     */
+	    :
+	    /* No outputs */
+	    :
+	    [registration]	"m"	(registration),
+	    [error]		"i"	(TCL_ERROR)
+	    :
+	    "%rax", "%rdx", "memory"
+	);
 
-	    "movq	$0x0,		0x0(%%rsp)"		"\n\t"
-	    "call	TkFinalize"			"\n\t"
+        /* Just do a regular C call so we don't need to worry about following
+         * the calling convention, specially the registers the function may
+         * clobber: */
+        TkFinalize(NULL);
 
+	__asm__ __volatile__ (
 	    /*
 	     * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION
 	     * and store a TCL_OK status
@@ -188,11 +196,9 @@ DllMain(
 	    :
 	    /* No outputs */
 	    :
-	    [registration]	"m"	(registration),
-	    [ok]		"i"	(TCL_OK),
-	    [error]		"i"	(TCL_ERROR)
+	    [ok]		"i"	(TCL_OK)
 	    :
-	    "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "memory"
+	    "%rax", "%rdx", "memory"
 	);
 
 #   else
@@ -218,12 +224,18 @@ DllMain(
 
 	    "movl	%%edx,		%%fs:0"		"\n\t"
 
-	    /*
-	     * Call TkFinalize
-	     */
+	    :
+	    /* No outputs */
+	    :
+	    [registration]	"m"	(registration),
+	    [error]		"i"	(TCL_ERROR)
+	    :
+	    "%eax", "%ebx", "%edx", "memory"
+	);
+
+        TkFinalize(NULL);
 
-	    "movl	$0x0,		0x0(%%esp)"		"\n\t"
-	    "call	_TkFinalize"			"\n\t"
+	__asm__ __volatile__ (
 
 	    /*
 	     * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION
@@ -259,11 +271,9 @@ DllMain(
 	    :
 	    /* No outputs */
 	    :
-	    [registration]	"m"	(registration),
-	    [ok]		"i"	(TCL_OK),
-	    [error]		"i"	(TCL_ERROR)
+	    [ok]		"i"	(TCL_OK)
 	    :
-	    "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
+	    "%eax", "%ebx", "%edx", "memory"
 	);
 
 #   endif

jan.nijtmans added on 2025-11-12 10:03:23:

Unfortunately, the build breaks for the --enable-symbols build:

https://github.com/tcltk/tk/actions/runs/19290295988/job/55159219445

Sorry, I have to revert this patch for now.


oscarfv added on 2025-11-11 18:44:34:
About those labels in the asm blocks in DllMain...

It is possible to move enough code to C so not to use labels within the asm blocks at all (using the GNU extension for taking the address of a label).

But that trickery of eating up the exception and pretending that nothing happened by just restoring the rbp/rsp registers to the values they had before the call to TkFinalize... it looks gross to me.

Do we really want to hide those exceptions? TkFinalize might corrupt memory and the embedding application would be none the wiser.

So this is about an application that embeds Tk, unloads it, some horrible thing happens in TkFinalize... and we want for the application to go its merry way. Is this realistic? Is it the right thing to do?

What if we delegate to the embedding application the handling of those exceptions?

oscarfv added on 2025-11-11 16:11:59:
Where does Tcl has such assembler? In tclWin32Dll.c there is an assembler block, but it does something different.

I searched the Tcl source code for __asm__ and, indeed, there are a few places for emulating SEH with __asm__. However:

1. Those are for 32 bit Windows only.

2. They wrap system calls (CloseHandle, CopyFile, MoveFile). None of them throws exceptions under normal circumstances. Only CloseHandle

"If the application is running under a debugger, the function will throw an exception if it receives either a handle value that is not valid or a pseudo-handle value."

https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle

IMO wrapping those calls with __try .. __catch (and the equivalent __asm__ hacks) is unnecessary.

OTOH, something in the comments of those __asm__ blocks catched my eye:

/* ... Note that this needs
     * to be one block of asm, to avoid stack imbalance; also, it is illegal
     * for one asm block to contain a jump to another.
     */

My patch does not jump from one block to another, but in the first block it takes the address of a label defined in the second block. Before sending the patch I checked that the address is correct by looking into the generated assembler code with gdb. The binary was compiled with -O2. Gcc has "asm goto" for dealing with labels defined outside of the current asm block. I'll investigate this when I have some spare time.

jan.nijtmans added on 2025-11-11 15:25:24:

Just a question: Tcl has such assembler-code as well. Does Tcl have the same problem?


jan.nijtmans added on 2025-11-11 15:11:33:

Fixed [9b98d74b754b9d75|here]. Thanks for the patch!


oscarfv added on 2025-11-10 12:31:20:
Forgot to mention that the original code was wrong on this too:

	    "movq	$0x0,		0x0(%%rsp)"		"\n\t"
	    "call	TkFinalize"			"\n\t"

On AMD64 the parameter is passed on a register, not on the stack.

Until now this worked because TkFinalize does not use its argument and that position of the stack apparently does not contain important stuff.

By moving the call from assembler to C, we fix that bug too.

In fact, there is more there that could be moved from assembler to C, but for now let's limit the patch to what's strictly necessary to address the reported crash.

jan.nijtmans added on 2025-11-07 22:01:56:

Sounds like a good idea. Thanks!