Skip to content

Commit 51a2783

Browse files
committed
mg.c: Perl_magic_get() dont call libc's getter func _errno() over and over
Ever since threads and SMP motherboards were invented, C's grammer token errno has been a function call returning an int * and not a extern "C" global data variable. Whether C grammer token is an inline asm intrinsic macro, or a traditional linker symbol in the C lang's symbol table, doesn't matter. On Windows errno is a macro to int * _errno(void) from ucrtbase.dll The UCRT dll from its day 1 upto atleast the UCRT dllfrom Win 10 ~2019, has a severe multi-eval bug in its C++/CPP getter method for its core TLS fetcher function. The multi-eval problem involves GetProcAddress(), and dynamic dispatching between TlsGetValue() and FlsGetValue(), and the rule that non-inlined function calls may never be de-duped for any reason. C++ operator overloading and CPP #define will never turn 10 method calls in a .i file or C++ template, into 1 method call and 1 POD size_t/void * variable. VC6, all msvcrt.dlls thru VC 2013, correctly only execute TlsGetValue() once and cache the result. UCRT does not. A pathologic reading of the POSIX spec, guarentees sv_setnv() UBed the value inside errno, through some ISO C lexer token inside the sv.i file made from sv.c that defines the body of sv_setnv(). If libc.so is chmod to --x by root user, how can a user prove the machine code inside libc's memcpy() does not call libc's sqrt() function? All behavior is unspecified and valid until it is defined. A realistic, not pedantic, location where errno was UBed could be these 2 lines: SV_CHECK_THINKFIRST_COW_DROP(sv); sv_upgrade(sv, SVt_PVNV); This patch was written for Win32 perf reasons, and not POSIX/C compliance. The later are an afterthought. To fix all of the above, cache the retval of errno. The ticket for this patch has a before/after.
1 parent 69b5e8a commit 51a2783

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

mg.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,20 +1009,20 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
10091009
{
10101010
dSAVE_ERRNO;
10111011
#ifdef VMS
1012-
sv_setnv(sv, (NV)((errno == EVMSERR) ? vaxc$errno : errno));
1012+
sv_setnv(sv, (NV)((saved_errno == EVMSERR) ? vaxc$errno : saved_errno));
10131013
#else
1014-
sv_setnv(sv, (NV)errno);
1014+
sv_setnv(sv, (NV)saved_errno);
10151015
#endif
10161016
#ifdef OS2
1017-
if (errno == errno_isOS2 || errno == errno_isOS2_set)
1017+
if (saved_errno == errno_isOS2 || saved_errno == errno_isOS2_set)
10181018
sv_setpv(sv, os2error(Perl_rc));
10191019
else
10201020
#endif
1021-
if (! errno) {
1021+
if (! saved_errno) {
10221022
SvPVCLEAR(sv);
10231023
}
10241024
else {
1025-
sv_string_from_errnum(errno, sv);
1025+
sv_string_from_errnum(saved_errno, sv);
10261026
/* If no useful string is available, don't
10271027
* claim to have a string part. The SvNOK_on()
10281028
* below will cause just the number part to be valid */

0 commit comments

Comments
 (0)