Skip to content

win32: allow build with USE_ITHREADS=undef but USE_IMP_SYS=define #23178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: blead
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,10 @@ L</Modules and Pragmata> section.

=over 4

=item XXX-some-platform
=item Win32

XXX
Fix builds with C<USE_IMP_SYS> defined but C<USE_ITHREADS> not
defined.

=back

Expand Down
19 changes: 18 additions & 1 deletion win32/perllib.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,17 @@ xs_init(pTHX)

#include "perlhost.h"

#define PANIC_THREAD_ID_MSG "panic: thread id mismatch\n"

#define panic_thread_id() \
(void)WriteFile(GetStdHandle(STD_ERROR_HANDLE), \
PANIC_THREAD_ID_MSG, sizeof(PANIC_THREAD_ID_MSG)-1, \
NULL, NULL)

void
win32_checkTLS(PerlInterpreter *host_perl)
{
#ifdef USE_ITHREADS
/* GCurThdId() is lightweight, but b/c of the ctrl-c/signals sometimes firing
in other random WinOS threads, that make the TIDs go out of sync.
This isn't always an error, although high chance of a SEGV in the next
Expand All @@ -62,11 +70,20 @@ win32_checkTLS(PerlInterpreter *host_perl)
if(tid != host_perl->Isys_intern.cur_tid) {
dTHX; /* heavyweight */
if (host_perl != my_perl) {
int *nowhere = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave JHI's/NIS's/Sarathy's forced crash in place, or change it to DebugBreak() or __debugbreak(). If this branch/text, is reached, the end user 100% needs to open GDB or VS IDE C debugger immediately. DebugBreak() and __debugbreak() generate a different distinct 0xC0000,00__ exception code from 0xC000,00_SEGV_UNMAPPED_ADDR. Your tech-illiterate end users will see the different 0xC0000,00__ vs 0xC000,00_SEGV_UNMAPPED_ADDR. error code in the WinOS GUI crash popup box. And its definitely cleaner/more dev friendly/senior citizen friendly to, umm, "violently" end a process with an error code that means "the C code intentionally voluntarily violently killed the process" vs "the C code has a logic flaw and violently killed the process".

Deref-ing mem address 0, and executing __debugbreak() bring up the exact same WinOS GUI crash/WER popup, with the same "Debug now" button to click on, for P5P/CPAN XS author use so there is no harm or downside to switching from "intentional deref addr 0 crash" to "intentionally requested crash and advise end user to figure out the rest with their C debugger if they know how to use it".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What forced crash? There hasn't been a crash here since 7bd379e. int *nowhere = NULL is a no-nop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake, I'm was remembering src code from ancient Perls, and the abort(); right below looks GUI identical to a SEGV on Windows at runtime and in a C debugger, just with a different 0xC00000__ crash code from 0xc0000005 ("Access Violation", real illegal deref). I don't pay much visual attention to the crash codes. SIGILL or SIGBUS or SIGSEGV. Same thing [tech diff is trivial]. Same diagnostics/fix procedures.

panic_thread_id();
DebugBreak();
abort();
}
host_perl->Isys_intern.cur_tid = tid;
}
#elif defined(PERL_MULTIPLICITY)
dTHX;
if (host_perl != my_perl) {
panic_thread_id();
DebugBreak();
abort();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have zero trust, in ascii token abort() safely stopping all execution of (P5P || CPAN XS author || end user || random 3rd party .dll) controlled (PP || C || C++) code in a Win32 process.

Copy link
Contributor

@bulk88 bulk88 Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have zero trust, in ascii token abort() safely stopping all execution of (P5P || CPAN XS author || end user || random 3rd party .dll) controlled (PP || C || C++) code in a Win32 process.

MS SDL security policy says abort() is forbidden to be used if a perma-assert() decides blackhat machine code is executing inside a Win32 process. Win 8 or Win 10 kernel introduced a user mode __fastfail() x86/x64/ARM CPU opcode to guarantee a Win32 process and its address space 100% stops all execution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Poking around inside machine code of msvcrt.dll shows, libc abort(), can theoretically resume PP code execution through PP's %SIG by executing MS CRT's libc's abort extern C function, plus MS CRT's abort sends out SEH "events" to all active listening registered SEH handlers in the process. 95%-100% of "all active listening registered SEH handlers" are usually exception frames created by C++ lang's try/catch/throw keywords, even WinPerl with P5P default build config out of the box, adds its own SEH event listener callback, with a requested priority of 'Z', so it runs as later as technologically possible, after all C++/C89 try/throw/catch stuff executed, and as the very very last catch frame, before WinOS Kernel draws the WER crash GUI popup box.

Although MS's SEH exception events/dispatch API is language neutral and available in Win32/64 assembly and ISO C89 lang code if someone wants to use the SEH API, 99% of real life catch frames will be random C++ lang code. But the problem is, from my opinion, P5P/me/no developer on earth, knows at "HW fault throw" time, or "SEGV event callback event listener invoke loop time", how many, if any, and where those exception frames came from, or who/what in virtual address space, put their callbacks on the non-public Win Kernel event listener array of things that want to listen to the Win Kernel's SEGV event queue in user mode. So something like MS CRT's "abort()", which uses "warning class (0x4____)" error 0x40000015 STATUS_FATAL_APP_EXIT, something in the SEH stack might have the bright idea to trap/resume, because its 0x4___ "warning class error" which supposedly means "informational" and "normal control flow sometimes"

And abort() isn't using a "0x8___" class error which means (corrupt || unknown || invalid || junk bytes || freed) (object instance || handle || FD || obj ptr)

or the 0xC___ class errors, which are "call 911/112" emergencies, since these are unrecoverable physical hardware errors, SEGVs, SIGILL, SIGBUS, integer div by zero, HW FP math exceptions, or a PCIe device disappeared from the PCIe bus randomly, etc. Nobody, even as a 1st timer coder, would try to trap resume those 0xC___ errors/or the NTSTATUS .h C constants behind those 0xC___ codes at runtime, and anything who knows what the 0xC___ class codes even are, knows what they are doing if they test for them in a SEH catch filter block.

Don't quote me, and I don't feel like googling it, but some, maybe upto half the 0xC___ codes, are documented by MS as non-resumable even if the catch block specifically ask the OS to resume execution with its (end user supplied) CPU register context state snapshot. But remember, nothing will stop a catch block, from synchronously, in normal C89, from executing a Perl_call_sv(); and letting some PP code execute ;-)

whats wrong with writing a Win32 C debugger in Pure Perl and publishing it on CPAN? Nothing, it could be a 100% legit useful CPAN tool lol.

}
#endif
}

EXTERN_C void
Expand Down
Loading