-
Notifications
You must be signed in to change notification settings - Fork 577
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
base: blead
Are you sure you want to change the base?
Conversation
Discovered while trying to test Perl#17601 since the build failed with: perllib.c(62): error C2039: 'cur_tid': is not a member of 'interp_intern' ...\perl\win32\win32.h(566): note: see declaration of 'interp_intern' perllib.c(68): error C2039: 'cur_tid': is not a member of 'interp_intern' ...\perl\win32\win32.h(566): note: see declaration of 'interp_intern'
This was used rather questionably to crash perl, stopping in the debugger if there is one, but that was removed in 7bd379e.
This patch is broken and using the wrong macro test and should not be in blead as currently written. BUT!!!! BUT!!!! No
This PR has a strategic/long term problem that needs some talk. Since C func
I do see I made a mistake by not locally having a no-threads blead perl perma-installed to test with, but, there are 2 design choices I need another persons opinion on:
The very specific and very real hazard, that WinPerl, thds and less-so (much-less-so ???) hazard, is unexpected execution of, a CPAN XS author's, C function ptrs, which are iterator C callbacks, that internally execute
Then any of the 4 above, will RANDOMLY execute Mr/Mrs CPAN XS author's iterator, either as
Permutation # 2 needs Mr/Mrs CPAN author to add about 1-3 pages of Perl C code to their XS module to have their iterator callback run safely, the 1-3 pages of Perl C code needed to do this has 5-10 different correct and safe versions/implementations on how to do this safely scattered around on grep.metacpan.org/perlmonks/stack overflow. Basically safely freeze/pause/wait/deep sleep the From the P5P WinPerl side of things, how important is it to stop the severe mem corruption that will instantly happen when 1 Microsoft MSDN/official API docs do a very very poor job documenting if they call user provided func ptrs, syncron or in a thread pool. Its If we document it as async/scalable, and a C dev catches/reverse engineers we executed their callback syncron when our API docs said the iterator is async into another thread, we get a lawsuit for deceptive trade practices because an ad tech company lost millions of $$$ because their TTFB serving an ad increased by 3 milliseconds per ad served. CPAN's JDB's Win32.pm/Win32.xs got bitten in 2021 by accidental threadpool drama when a new perl XSUB got added to Win32.pm. It was fixed in a few days/weeks and is now a non-issue, but this happens even in the 2020s, so some thinking needs to be done, how much protection, if any protection, and when and where and how often, to do the protection checks at runtime, WinPerl, no-thd and threaded, needs, against this hazard. Someones, anyones, 2nd opinion, is needed on the topic. I have my own opinions and gut instinct of what I want to do, or how I want to "solve" this hazard, but I want someone else to think over my thinking. |
@@ -62,11 +63,16 @@ win32_checkTLS(PerlInterpreter *host_perl) | |||
if(tid != host_perl->Isys_intern.cur_tid) { | |||
dTHX; /* heavyweight */ | |||
if (host_perl != my_perl) { | |||
int *nowhere = NULL; |
There was a problem hiding this comment.
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".
There was a problem hiding this comment.
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.
#else | ||
dTHX; | ||
if (host_perl != my_perl) { | ||
abort(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
if there is one. Previously this would exit silently and mysteriously, and unlike POSIX-likes abort() doesn't generally break into the debugger on Win32.
The inclusion of Lines 581 to 583 in df4834b
and the missing The entire function is already guarded by Lines 47 to 54 in df4834b
From what I can see, this check is a protection against bugs, not against an attacker. I've added a panic message (via WriteFile()) and DebugBreak(), since abort() doesn't break into the debugger as it typically does on POSIX-likes. |
That code failed to build for a different reason with implicit sys enabled and no multiplicity. Even with this change such a build fails later on for unrelated reasons:
but I'm not going to try to fix that here. |
I'm not going to address that mess of permutations in this PR, and this PR isn't about that mess of WinPerl build config flag permutations. Its for another PR if there ever is one by me or someone else.
Correct, this is a check against accidental thread-pooling of a
Your new version is perfect.
Remember, this class of accidental thread-pool errors, might be very hard/impossible to reproduce, if the WinPerl process (any process) is started from inside VS IDE's C debugger, or MS's TUI-ish windbg.exe C debugger, since ntdll.dll/kernel32.dll start to behave very very different at runtime if the process was started by a C debugger, and not a normal "very very different" means all the max-runtime-asserting features in |
What does that build flag even mean in real life/production code purpose? Why does a no-thds libperl.dll, either
need to virtualize PP level or XS level |
We supply those options, just as we do on non-Win32. If we're not going to support them, we can remove them, if we leave them in it's reasonable to fix them. I'm not saying we should put huge amounts of effort into fixing them but the actual fix here has been reasonably small and obvious. |
Thought up a theoretical production use of no-thd libperl with CPerlHost on. 2 different publisher single threaded local GUI root processes, GTK or C89 from 89 User32.dll, WX, QT local GUI app. A 3rd party plugin, which itself is a .dll/.so has to load and unload a libperl.so/.dll in and out of address space on command from the root process, and there is no Now how does 1 no-thd libperl.so.dll binary made by 1 dev, execute in 2 other root procs, different authors, one QT and one GTK? and have a "clean unload" of that libperl and its XS modules? CPerlHost/USE_IMP_SYS/Win32 psuedo-fork's "clean leak free exit" hooks to the rescue in a no-thd libperl build config. "clean unload" production code example https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cofreeunusedlibrariesex
Same. The infrastructure is better left in as a semi history lesson than forgotten about in git blame and there is probably isn't that much of it, since ithreads on linux/winos and psuedo-fork are here to stay forever. Ive never seen a Linux distro ship a no-thd perl in their package manager. So Atleast aslong as CPAN XS authors stick (XSUB.h) or carrot stick to Hungarian notion Perl C macro API, its easier to hook random chunks of AnyOS LibC at random points in the future. Even if WinPerl declines to implement the vtable entry (and 90% of them are jump stubs (1997-5.41.11) and just falls back to whatever PosixPerl or win32_foo() in win32.c does, atleast the interp core .c code is ready for those libc hooks when they suddenly become needed, vs grep hunt-and-peck and OS/CC vendor conflicts for p5p and 3rd party header conflicts on cpan xs because ever large popular C/C++ framework's commit was PosixPerl's |
DIY-ed |
While testing #17601 the build failed with: