Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.9k stars 540 forks source link

successful s///e clobbers $! on MSWin32 #12652

Closed p5pRT closed 10 years ago

p5pRT commented 11 years ago

Migrated from rt.perl.org#116118 (status was 'resolved')

Searchable as RT116118$

p5pRT commented 11 years ago

From cm.perl@abtela.com

Created by cm.perl@abtela.com

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically   $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

Perl Info ``` Flags: category=core severity=low Site configuration information for perl 5.17.7: Configured by cm at Mon Dec 17 13:03:51 2012. Summary of my perl5 (revision 5 version 17 subversion 7) configuration: Derived from: Platform: osname=MSWin32, osvers=4.0, archname=MSWin32-x64-multi-thread uname='' config_args='undef' hint=recommended, useposix=true, d_sigaction=undef useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=define, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields', optimize='-s -O2', cppflags='-DWIN32' ccversion='', gccversion='4.6.3', gccosandvers='' intsize=4, longsize=4, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='long long', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='g++', ldflags ='-s -L"d:\perl\lib\CORE" -L"C:\MinGW\lib"' libpth=C:\MinGW\lib libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 libc=, so=dll, useshrplib=true, libperl=libperl517.a gnulibc_version='' Dynamic Linking: dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' ' cccdlflags=' ', lddlflags='-mdll -s -L"d:\perl\lib\CORE" -L"C:\MinGW\lib"' Locally applied patches: @INC for perl 5.17.7: D:/perl/site/lib D:/perl/lib . Environment for perl 5.17.7: CYGWIN=nodosfilewarning HOME=e:/cm LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=D:\perl\site\bin;D:\perl\bin;D:\c\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\PuTTY;C:\Program Files (x86)\OpenOffice.org 3\program;C:\Program Files (x86)\QT Lite\QTSystem;c:\Program Files\WinRAR;C:\Program Files (x86)\Calibre2\ PERL_BADLANG (unset) SHELL (unset) ```
p5pRT commented 11 years ago

From cm.perl@abtela.com

0001-Add-test-TODO-on-MSWin32-successful-s-e-does-not-clo.patch ```diff From 9765f5da1323607e17cb368c3d7e4cb75c31cbd0 Mon Sep 17 00:00:00 2001 From: Christian Millour Date: Mon, 17 Dec 2012 16:59:32 +0100 Subject: [PATCH] Add test (TODO on MSWin32): successful s///e does not clobber $! --- t/re/subst.t | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/t/re/subst.t b/t/re/subst.t index 8acd54f..5769ea1 100644 --- a/t/re/subst.t +++ b/t/re/subst.t @@ -7,7 +7,7 @@ BEGIN { require './test.pl'; } -plan( tests => 206 ); +plan( tests => 207 ); $_ = 'david'; $a = s/david/rules/r; @@ -886,3 +886,12 @@ $@ = "\x{30cb}eval 18"; $@ =~ s/eval \d+/eval 11/; is $@, "\x{30cb}eval 11", 'loading utf8 tables does not interfere with matches against $@'; + +TODO: { + local $TODO = "fails on $^O" if $^O eq 'MSWin32'; + local $! = my $arbitrary = 1; + my $arg = "a"; + # $arg =~ s/([[:cntrl:]]|[[:^ascii:]])/sprintf("\\x{%x}",ord($1))/eg; + $arg =~ s/(.)/"$1"/e; + is (0+$!, $arbitrary, 'successful s///e does not clobber $!'); +} -- 1.7.4 ```
p5pRT commented 11 years ago

From @demerphq

On 17 December 2012 19​:12\, Christian Millour \perlbug\-followup@​perl\.org wrote​:

# New Ticket Created by Christian Millour # Please include the string​: [perl #116118] # in the subject line of all future correspondence about this issue. # \<URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=116118 >

This is a bug report for perl from cm.perl@​abtela.com\, generated with the help of perlbug 1.39 running under perl 5.17.7.

----------------------------------------------------------------- [Please describe your issue here]

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 11 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail. As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!. It tests it badly\, as it turns out\, on MSWin32\, as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

p5pRT commented 11 years ago

From @doy

On Tue\, Dec 18\, 2012 at 12​:20​:31AM +0100\, Christian Millour wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail. As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!. It tests it badly\, as it turns out\, on MSWin32\, as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

From 'perldoc perlvar'​:

  Many system or library calls set "errno" if they fail\, to indicate the   cause of failure. They usually do not set "errno" to zero if they   succeed. This means "errno"\, hence $!\, is meaningful only immediately   after a failure.

Calling any function\, including functions from Carp\, can have unpredictable effects on $!. If you need to do things before using the value of $!\, you should save it in a lexical immediately after the system call which sets $!. carp() is certainly not the only function that behaves this way.

-doy

p5pRT commented 11 years ago

From @demerphq

On 18 December 2012 00​:20\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

No\, sorry. What you want to say is /... unless they call a system call which fails/.

Which is what happens here.

The regex engine may call out to disk to load code. This is a complex process which may involve any number of system calls setting $!.

As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Umm again no. As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!.

Well\, IMO they should not.

It tests it badly\, as it turns out\, on MSWin32\,

This is only tangentally related to Win32. It has to do with the regex encountering unicode and calling out to disk to load unicode data.

as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

If we are already trying hard not to change $! in croak then we should fix this behaviour. But I maintain it is not a bug. Or at least\, if it is a bug it is not that the regex engine might call out to disk.

Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 11 years ago

From @demerphq

On 18 December 2012 00​:27\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

On Tue\, Dec 18\, 2012 at 12​:20​:31AM +0100\, Christian Millour wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail. As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!. It tests it badly\, as it turns out\, on MSWin32\, as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

Calling any function\, including functions from Carp\, can have unpredictable effects on $!. If you need to do things before using the value of $!\, you should save it in a lexical immediately after the system call which sets $!. carp() is certainly not the only function that behaves this way.

Exactly. Thanks.

OTOH I can see carp/croak trying not to mess with $!\, if only so that

croak($!);

works. Which would mean that this is a bug that tied-vars of this type arent evaluated when they are put on the stack (iow a wont fix). It definitely isnt a bug that $! might change /after/ a call to carp().

cheers\, Yves

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 11 years ago

From @bulk88

On Mon Dec 17 10​:12​:56 2012\, cm.perl@​abtela.com wrote​:

This is a bug report for perl from cm.perl@​abtela.com\, generated with the help of perlbug 1.39 running under perl 5.17.7.

----------------------------------------------------------------- [Please describe your issue here]

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

Can not reproduce. I ran the attached file\, with one or the other line uncommented. All passed.

Summary of my perl5 (revision 5 version 17 subversion 7 patch blead 2012-12-06. 6​:42​:20 93a641ae382638ffd1980378be4810244d04f4b0 v5.17.6-186-g93a641a) configur tion​:   Snapshot of​: 93a641ae382638ffd1980378be4810244d04f4b0   Platform​:   osname=MSWin32\, osvers=5.1\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -GL -G7 -DWIN32 -D_ ONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPL CIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T'\,   optimize='-MD -Zi -DNDEBUG -O1 -GL -G7'\,   cppflags='-DWIN32'   ccversion='13.10.6030'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeks ze=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libp th​:"c​:\perl517\lib\CORE" -machine​:x86'   libpth="C​:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib"   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32. ib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_3 .lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdl 32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib w 2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib ms crt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl517.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf - tcg -libpath​:"c​:\perl517\lib\CORE" -machine​:x86'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE   PERL_PRESERVE_IVUV USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Dec 16 2012 13​:29​:13   @​INC​:   C​:/perl517/site/lib   C​:/perl517/lib   .

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @bulk88

[minitest 116118.pl](https://rt-archive.perl.org/perl5/Ticket/Attachment/1178906/605582/minitest 116118.pl)

p5pRT commented 11 years ago

From @Leont

On Tue\, Dec 18\, 2012 at 12​:27 AM\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

And from POSIX​:

  The value of errno shall be defined only after a call to a function   for which it is explicitly stated to be set and until it is changed   by the next function call or if the application assigns it a value.   The value of errno should only be examined when it is indicated to   be valid by a function's return value. … No function in this volume   of IEEE Std 1003.1-2001 shall set errno to 0. The setting of errno   after a successful call to a function is unspecified unless the   description of that function specifies that errno shall not be   modified.

Leon

p5pRT commented 11 years ago

From @doy

On Tue\, Dec 18\, 2012 at 12​:38​:33AM +0100\, demerphq wrote​:

On 18 December 2012 00​:27\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

On Tue\, Dec 18\, 2012 at 12​:20​:31AM +0100\, Christian Millour wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail. As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!. It tests it badly\, as it turns out\, on MSWin32\, as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

Calling any function\, including functions from Carp\, can have unpredictable effects on $!. If you need to do things before using the value of $!\, you should save it in a lexical immediately after the system call which sets $!. carp() is certainly not the only function that behaves this way.

Exactly. Thanks.

OTOH I can see carp/croak trying not to mess with $!\, if only so that

croak($!);

works. Which would mean that this is a bug that tied-vars of this type arent evaluated when they are put on the stack (iow a wont fix). It definitely isnt a bug that $! might change /after/ a call to carp().

If croak($!) doesn't work\, that is an actual bug. It's not particularly related to what has been discussed so far\, though\, as far as I can see.

-doy

p5pRT commented 11 years ago

From @bulk88

On Mon Dec 17 15​:40​:46 2012\, LeonT wrote​:

On Tue\, Dec 18\, 2012 at 12​:27 AM\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

And from POSIX​:

The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value of errno should only be examined when it is indicated to be valid by a function's return value. … No function in this volume of IEEE Std 1003.1-2001 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

Leon

Perl functions\, subs\, opcodes\, and operators do not always have one to one correspondence with POSIX C calls. Many C libs calls can make up one script level token.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @pjcj

On Tue\, Dec 18\, 2012 at 12​:39​:47AM +0100\, Leon Timmermans wrote​:

On Tue\, Dec 18\, 2012 at 12​:27 AM\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

And from POSIX​:

The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value of errno should only be examined when it is indicated to be valid by a function's return value. … No function in this volume of IEEE Std 1003.1-2001 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

Leon

The last time we discussed this on the list I think we came to the conclusion that there was no reason that we needed to keep $! so closely tied to errno. If we wanted to we /could/ set $! only on failure. I imagine it would be a fair amount of work though\, with numerous edge-cases\, which could be why no one has done it.

-- Paul Johnson - paul@​pjcj.net http​://www.pjcj.net

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 18/12/2012 00​:40\, bulk88 via RT a écrit :

Can not reproduce. I ran the attached file\, with one or the other line uncommented. All passed.

Forget about the commented line in the original test. It was intended as a reminder to myself of the origin of the bug. It was not intended to be used for the test since no substitution occurs when $arg is "a".

here is a session with strawberry perl portable 5.16.2 (a fresh portableshell.bat window)


  Welcome to Strawberry Perl Portable Edition!   * URL - http​://www.strawberryperl.com/   * see README.portable.TXT for more info


Perl executable​: C​:\strawberry-perl-5.16.2.1-64bit-portable\perl\bin\perl.exe Perl version : 5.16.2 / MSWin32-x64-multi-thread

C​:\strawberry-perl-5.16.2.1-64bit-portable>cat > minitest.pl #!/usr/bin/perl -w use Data​::Dumper; use warnings; use strict; use Test​::More tests => 1 ; {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   local $! = my $arbitrary = 1;   my $arg = "a";   $arg =~ s/(.)/"$1"/e;   is (0+$!\, $arbitrary\, 'successful s///e does not clobber $!'); }

C​:\strawberry-perl-5.16.2.1-64bit-portable>perl minitest.pl 1..1 not ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at minitest.pl line 11. # got​: '0' # expected​: '1'

C​:\strawberry-perl-5.16.2.1-64bit-portable>

but\, of course because it is a TODO test\, prove succeeds...

C​:\strawberry-perl-5.16.2.1-64bit-portable>prove minitest.pl minitest.pl .. ok All tests successful. Files=1\, Tests=1\, 0 wallclock secs ( 0.09 usr + 0.01 sys = 0.11 CPU) Result​: PASS

C​:\strawberry-perl-5.16.2.1-64bit-portable>

p5pRT commented 11 years ago

From @doy

On Mon\, Dec 17\, 2012 at 04​:14​:41PM -0800\, bulk88 via RT wrote​:

On Mon Dec 17 15​:40​:46 2012\, LeonT wrote​:

On Tue\, Dec 18\, 2012 at 12​:27 AM\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

From 'perldoc perlvar'​:

Many system or library calls set "errno" if they fail\, to indicate the cause of failure. They usually do not set "errno" to zero if they succeed. This means "errno"\, hence $!\, is meaningful only immediately after a failure.

And from POSIX​:

The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value of errno should only be examined when it is indicated to be valid by a function's return value. … No function in this volume of IEEE Std 1003.1-2001 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

Leon

Perl functions\, subs\, opcodes\, and operators do not always have one to one correspondence with POSIX C calls. Many C libs calls can make up one script level token.

It does point out that this isn't a weird or idiosyncratic restriction\, though.

-doy

p5pRT commented 11 years ago

From @bulk88

On Mon Dec 17 16​:29​:15 2012\, cm.perl@​abtela.com wrote​:

C​:\strawberry-perl-5.16.2.1-64bit-portable>perl minitest.pl 1..1 not ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at minitest.pl line 11. # got​: '0' # expected​: '1'

C​:\strawberry-perl-5.16.2.1-64bit-portable>

but\, of course because it is a TODO test\, prove succeeds...

Still can't reproduce. I tried Perl 5.12 DEBUGGING and Perl 5.17 not DEBUGGING. Both VC 2003\, Perl on 32 bit x86 windows. Also not reproduced with 32 bit Perl 5.12.3 Strawberry. I see you used the "cat" command. You aren't running Cygwin or Cygwin Perl right?

_______________________________________________________________________ C​:\Documents and Settings\Owner\Desktop>perl minitest.pl 1..1 ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Owner\Desktop>perl -V Summary of my perl5 (revision 5 version 17 subversion 7 patch blead 2012-12-06.1 6​:42​:20 93a641ae382638ffd1980378be4810244d04f4b0 v5.17.6-186-g93a641a) configura tion​:   Snapshot of​: 93a641ae382638ffd1980378be4810244d04f4b0   Platform​:   osname=MSWin32\, osvers=5.1\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -GL -G7 -DWIN32 -D_C ONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLI CIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T'\,   optimize='-MD -Zi -DNDEBUG -O1 -GL -G7'\,   cppflags='-DWIN32'   ccversion='13.10.6030'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeksi ze=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpa th​:"c​:\perl517\lib\CORE" -machine​:x86'   libpth="C​:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib"   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.l ib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32 .lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt. lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg 32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws 2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msv crt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl517.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -l tcg -libpath​:"c​:\perl517\lib\CORE" -machine​:x86'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE   PERL_PRESERVE_IVUV USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Dec 16 2012 13​:29​:13   @​INC​:   C​:/perl517/site/lib   C​:/perl517/lib   .

C​:\Documents and Settings\Owner\Desktop> _______________________________________________________________________

C​:\Documents and Settings\Owner\Desktop>perl minitest.pl 1..1 ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Owner\Desktop>perl -V Summary of my perl5 (revision 5 version 12 subversion 2) configuration​:

  Platform​:   osname=MSWin32\, osvers=5.1\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -Od -MD -Zi -DDEBUGGING -DWIN32 -D_CONSOL E -DNO_STRICT -DHAVE_DES_FCRYPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DU SE_PERLIO'\,   optimize='-Od -MD -Zi -DDEBUGGING'\,   cppflags='-DWIN32'   ccversion='13.10.3077'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeksi ze=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -libpath​:"c​:\perl512\lib\ CORE" -machine​:x86'   libpth="c​:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib"   libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32 .lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_ 32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcr t.lib   perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comd lg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib m svcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl512.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -libpath​:"c​:\p erl512\lib\CORE" -machine​:x86'

Characteristics of this binary (from libperl)​:   Compile-time options​: DEBUGGING MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_TRACK_MEMPOOL PL_OP_SLAB_ALLOC   USE_ITHREADS USE_LARGE_FILES USE_PERLIO   USE_PERL_ATOF   Built under MSWin32   Compiled at Mar 23 2011 08​:10​:43   %ENV​:   PERL_JSON_BACKEND="JSON​::XS"   PERL_YAML_BACKEND="YAML"   @​INC​:   C​:/perl512/site/lib   C​:/perl512/lib   .

C​:\Documents and Settings\Owner\Desktop> _______________________________________________________________________ C​:\Documents and Settings\Owner\Desktop>perl minitest.pl 1..1 ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Owner\Desktop>perl -V Summary of my perl5 (revision 5 version 12 subversion 3) configuration​:

  Platform​:   osname=MSWin32\, osvers=5.1\, archname=MSWin32-x86-multi-thread   uname='Win32 strawberryperl 5.12.3.0 #1 Sun May 15 09​:44​:53 2011 i386'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields DPERL_MSVCRT_READFIX'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.4.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lsee size=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++'\, ldflags ='-s -L"C​:\sperl\perl\lib\CORE" -L"C​:\sperl\c\lib"'   libpth=C​:\sperl\c\lib C​:\sperl\c\i686-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi3 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversio -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladv pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lve sion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl512.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\sperl\perl\lib\CORE" -L"C​:\sperl\ \lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS   USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF   USE_SITECUSTOMIZE   Built under MSWin32   Compiled at May 15 2011 17​:02​:01   %ENV​:   PERL_JSON_BACKEND="JSON​::XS"   PERL_YAML_BACKEND="YAML"   @​INC​:   C​:/sperl/perl/site/lib   C​:/sperl/perl/vendor/lib   C​:/sperl/perl/lib   .

C​:\Documents and Settings\Owner\Desktop> _______________________________________________________________________ C​:\Documents and Settings\Owner\Desktop>type minitest.pl #!/usr/bin/perl -w use Data​::Dumper; use warnings; use strict; use Test​::More tests => 1 ; { local $TODO = "fails on $^O" if $^O eq 'MSWin32'; local $! = my $arbitrary = 1; my $arg = "a"; $arg =~ s/(.)/"$1"/e; is (0+$!\, $arbitrary\, 'successful s///e does not clobber $!'); }

C​:\Documents and Settings\Owner\Desktop> _______________________________________________________________________ -- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @ikegami

On Mon\, Dec 17\, 2012 at 6​:20 PM\, Christian Millour \cm\.perl@&#8203;abtela\.comwrote​:

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

Nothing offers that guarantee\, not even C\\, C\ and C\!

p5pRT commented 11 years ago

From @ikegami

On Mon\, Dec 17\, 2012 at 7​:03 PM\, Jesse Luehrs \doy@&#8203;tozt\.net wrote​:

If croak($!) doesn't work\, that is an actual bug. It's not particularly related to what has been discussed so far\, though\, as far as I can see.

If croak($!) doesn't work\, there's a good chance that croak($_) and croak($1). Passing globals to subs is always dangerous.

p5pRT commented 11 years ago

From @bulk88

On Mon Dec 17 20​:14​:17 2012\, bulk88 wrote​:

Still can't reproduce. I tried Perl 5.12 DEBUGGING and Perl 5.17 not DEBUGGING. Both VC 2003\, Perl on 32 bit x86 windows. Also not reproduced with 32 bit Perl 5.12.3 Strawberry. I see you used the "cat" command. You aren't running Cygwin or Cygwin Perl right?

Trying x64 Windows perl. Still can't reproduce. _______________________________________________________________________ C​:\Documents and Settings\Administrator\Desktop>perl minitest.pl 1..1 ok 1 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Administrator\Desktop>perl -V Summary of my perl5 (revision 5 version 17 subversion 7 patch blead 2012-12-06.1 6​:42​:20 93a641ae382638ffd1980378be4810244d04f4b0 v5.17.6-186-g93a641a) configura tion​:   Snapshot of​: 93a641ae382638ffd1980378be4810244d04f4b0   Platform​:   osname=MSWin32\, osvers=5.2\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -GL -GS- -favor​:AMD6 4 -fp​:precise -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -DCONSERVATIVE -D_CRT_SECUR E_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLI CIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO'\,   optimize='-MD -Zi -DNDEBUG -O1 -GL -GS- -favor​:AMD64 -fp​:precise'\,   cppflags='-DWIN32'   ccversion='15.00.30729.01'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='__int64'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lsee ksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -ltcg -libpath​:"c​:\p517\lib\CORE" -machine​:AMD64 "/manifestdependency​:type='Win32' na me='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture=' *' publicKeyToken='6595b64144ccf1df' language='*'"'   libpth=\lib   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.l ib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32 .lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt. lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg 32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws 2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib msv crt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl517.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -l tcg -ltcg -libpath​:"c​:\p517\lib\CORE" -machine​:AMD64 "/manifestdependency​:type ='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArc hitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE   PERL_PRESERVE_IVUV USE_64_BIT_INT USE_ITHREADS   USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE   USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO   USE_PERL_ATOF   Built under MSWin32   Compiled at Dec 6 2012 20​:35​:02   @​INC​:   C​:/p517/site/lib   C​:/p517/lib   .

C​:\Documents and Settings\Administrator\Desktop> ______________________________________________________________________

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @bulk88

On Mon Dec 17 20​:37​:57 2012\, bulk88 wrote​:

Trying x64 Windows perl. Still can't reproduce.

Trying Cygwin. Still can't reproduce. ______________________________________________________________________ Administrator@​dl585 ~/Desktop $ perl minitest.pl 1..1 ok 1 - successful s///e does not clobber $!

Administrator@​dl585 ~/Desktop $ perl -V Summary of my perl5 (revision 5 version 14 subversion 2) configuration​:

  Platform​:   osname=cygwin\, osvers=1.7.15(0.26053)\, archname=cygwin-thread-multi-64int   uname='cygwin_nt-5.1 winxp 1.7.15(0.26053) 2012-05-09 10​:25 i686 cygwin '   config_args='-de -Dlibperl=cygperl5_14.dll -Dcc=gcc-4 -Dld=g++-4 -Darchname=i686-cygwin-threads-64int -Dmksymlinks -Dusethreads -Accflags=-g'   hint=recommended\, useposix=true\, d_sigaction=define   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc-4'\, ccflags ='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g -fno-strict-aliasing -pipe -fstack-protector'\,   optimize='-O3'\,   cppflags='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g -fno-strict-aliasing -pipe -fstack-protector'   ccversion=''\, gccversion='4.5.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++-4'\, ldflags =' -Wl\,--enable-auto-import -Wl\,--export-all-symbols -Wl\,--enable-auto-image-base -fstack-protector -L/usr/local/lib'   libpth=/usr/local/lib /usr/lib /lib   libs=-lgdbm -ldb -ldl -lcrypt -lgdbm_compat   perllibs=-ldl -lcrypt   libc=/usr/lib/libc.a\, so=dll\, useshrplib=true\, libperl=cygperl5_14.dll   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags=' --shared -Wl\,--enable-auto-import -Wl\,--export-all-symbols -Wl\,--enable-auto-image-base -L/usr/local/lib -fstack-protector'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_PRESERVE_IVUV   PERL_USE_SAFE_PUTENV USE_64_BIT_INT USE_ITHREADS   USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF   USE_REENTRANT_API   Locally applied patches​:   Bug#55162 File​::Spec​::case_tolerant performance   CYG07 $vendorarch/auto/.rebase   CYG15 static Win32CORE   CYG17 cyg-1.7 paths-utf8   0c612ce82 Fix building static extensions on cygwin\, -UUSEIMPORTLIB   1bac5ecc1 Fix 64-bit threading sv.c​: S_anonymise_cv_maybe   Cygwin​::sync_winenv added   Built under cygwin   Compiled at Jul 12 2012 14​:17​:21   %ENV​:   PERL_JSON_BACKEND="JSON​::XS"   PERL_YAML_BACKEND="YAML"   CYGWIN="tty"   @​INC​:   /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int   /usr/lib/perl5/site_perl/5.14   /usr/lib/perl5/vendor_perl/5.14/i686-cygwin-threads-64int   /usr/lib/perl5/vendor_perl/5.14   /usr/lib/perl5/5.14/i686-cygwin-threads-64int   /usr/lib/perl5/5.14   /usr/lib/perl5/site_perl/5.10   /usr/lib/perl5/vendor_perl/5.10   /usr/lib/perl5/site_perl/5.8   .

Administrator@​dl585 ~/Desktop $ ______________________________________________________________________

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 18/12/2012 05​:14\, bulk88 via RT a écrit :

Still can't reproduce. I tried Perl 5.12 DEBUGGING and Perl 5.17 not DEBUGGING. Both VC 2003\, Perl on 32 bit x86 windows. Also not reproduced with 32 bit Perl 5.12.3 Strawberry. I see you used the "cat" command. You aren't running Cygwin or Cygwin Perl right?

I am generally running Cygwin with strawberry perl portable (SPP) with no problem whatsoever\, provided I am careful with PATH. spp.log (attached) gives an example.

I have tried running a SPP portable window from an other machine (a fresh Windows Server 2008 R2 standard SP1\, without Cygwin) and get the error. See ts-spp.log (attached).

On this same machine I have installed Active State Perl and also get the error (see as.log\, attached).

If I am doing something wrong I really can't understand what it is. Could you please have a look at the attached logs and tell me what is amiss ?

Many thanks in advance\, and best regards

p5pRT commented 11 years ago

From cm.perl@abtela.com

Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C​:\Users\Administrator>c​:\Perl64\bin\perl -V Summary of my perl5 (revision 5 version 16 subversion 1) configuration​:

  Platform​:   osname=MSWin32\, osvers=5.2\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -Ox -GL -fp​:precise -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -D USE_PERLIO'\,   optimize='-MD -Zi -DNDEBUG -Ox -GL -fp​:precise'\,   cppflags='-DWIN32'   ccversion='14.00.40310.41'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='__int64'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'   libpth=\lib   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib bufferoverflowU.lib msvcrt.lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32. lib comctl32.lib bufferoverflowU.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl516.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   USE_SITECUSTOMIZE   Locally applied patches​:   ActivePerl Build 1601 [296175]   Built under MSWin32   Compiled at Aug 30 2012 18​:41​:50   @​INC​:   c​:/Perl64/site/lib   c​:/Perl64/lib   .

C​:\Users\Administrator>type \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } }

C​:\Users\Administrator>C​:\Perl64\bin\perl -w \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl 1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl line 12. # got​: '0' # expected​: '1'

C​:\Users\Administrator>

p5pRT commented 11 years ago

From cm.perl@abtela.com

Taisha​:\~/perl/patches/badcarp $ cat onesubst.pl use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } } Taisha​:\~/perl/patches/badcarp $ env | sort ALLUSERSPROFILE=C​:\ProgramData APPDATA=C​:\Users\cm\AppData\Roaming COMMONPROGRAMFILES=C​:\Program Files (x86)\Common Files COMPUTERNAME=TAISHA COMSPEC=C​:\Windows\system32\cmd.exe CYGWIN=nodosfilewarning CommonProgramFiles(x86)=C​:\Program Files (x86)\Common Files CommonProgramW6432=C​:\Program Files\Common Files DISPLAY= EMACS=t EMACSDATA=E​:/applis/ntemacs24/etc EMACSDOC=E​:/applis/ntemacs24/etc EMACSLOADPATH=E​:/applis/ntemacs24/site-lisp;E​:/applis/ntemacs24/../site-lisp;E​:/applis/ntemacs24/lisp;E​:/applis/ntemacs24/leim EMACSPATH=E​:/applis/ntemacs24/bin EM_PARENT_PROCESS_ID=14132 ESHELL=bash FP_NO_HOST_CHECK=NO FTP_PASSIVE=1 HOME=/cygdrive/e/cm HOMEDRIVE=C​: HOMEPATH=\Users\cm INSIDE_EMACS=24.0.50.1\,comint LANG=C LOCALAPPDATA=C​:\Users\cm\AppData\Local LOGONSERVER=\\TAISHA NUMBER_OF_PROCESSORS=8 OLDPWD=/cygdrive/d/perls/blead/perl-git/dist/Carp/t OPENSSL_CONF=C​:\OpenSSL-Win64\bin\openssl.cfg OS=Windows_NT PATH=/usr/local/bin​:/usr/bin​:/bin​:/cygdrive/c/Windows/system32​:/cygdrive/c/Windows​:/cygdrive/c/Windows/System32/Wbem​:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0​:/cygdrive/c/Program Files (x86)/PuTTY​:/cygdrive/c/Program Files (x86)/OpenOffice.org 3/program​:/cygdrive/c/Program Files (x86)/QT Lite/QTSystem​:/cygdrive/c/Program Files/WinRAR​:/cygdrive/c/Program Files (x86)/Calibre2 PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC PROCESSOR_ARCHITECTURE=x86 PROCESSOR_ARCHITEW6432=AMD64 PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 26 Stepping 5\, GenuineIntel PROCESSOR_LEVEL=6 PROCESSOR_REVISION=1a05 PROGRAMFILES=C​:\Program Files (x86) PS1=\h​:\w \$ PS2=> PSModulePath=C​:\Windows\system32\WindowsPowerShell\v1.0\Modules\ PUBLIC=C​:\Users\Public PWD=/cygdrive/e/cm/perl/patches/badcarp ProgramData=C​:\ProgramData ProgramFiles(x86)=C​:\Program Files (x86) ProgramW6432=C​:\Program Files SESSIONNAME=Console SHELL=bash SHLVL=1 SWPDIR=E​:\\AI\\AI41E\\Tradfact\\swpdir SYSTEMDRIVE=C​: SYSTEMROOT=C​:\Windows TEMP=/cygdrive/c/Users/cm/AppData/Local/Temp TERM=emacs TERMCAP=emacs​:co#188​:tc=unknown​: TMP=/cygdrive/c/Users/cm/AppData/Local/Temp TMPDIR=/cygdrive/c/Users/cm/AppData/Local/Temp TZ=MET-1MEST USERDOMAIN=Taisha USERNAME=cm USERPROFILE=C​:\Users\cm WINDIR=C​:\Windows _=/usr/bin/env __COMPAT_LAYER=ElevateCreateProcess emacs_dir=E​:/applis/ntemacs24 Taisha​:\~/perl/patches/badcarp $ for VERSION in 5.12.3.0 5.14.3.1-32bit 5.14.3.1-64bit 5.16.1.1-64bit 5.16.2.1-32bit 5.16.2.1-64bit; do \ echo "================================================================================"; \ ROOT=/cygdrive/c/strawberry-perl-${VERSION}-portable PATH=$ROOT/perl/site/bin​:$ROOT/perl/bin​:$ROOT/c/bin perl -V; \ echo "--------------------------------------------------------------------------------"; \ ROOT=/cygdrive/c/strawberry-perl-${VERSION}-portable PATH=$ROOT/perl/site/bin​:$ROOT/perl/bin​:$ROOT/c/bin perl onesubst.pl; \ done

================================================================================ Summary of my perl5 (revision 5 version 12 subversion 3) configuration​:  
  Platform​:   osname=MSWin32\, osvers=5.1\, archname=MSWin32-x86-multi-thread   uname='Win32 strawberryperl 5.12.3.0 #1 Sun May 15 09​:44​:53 2011 i386'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields -DPERL_MSVCRT_READFIX'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.4.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.12.3.0-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.12.3.0-portable\c\lib"'   libpth=C​:\strawberry-perl-5.12.3.0-portable\c\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl512.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.12.3.0-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.12.3.0-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS   USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF   USE_SITECUSTOMIZE   Built under MSWin32   Compiled at May 15 2011 14​:40​:22   @​INC​:   C​:/strawberry-perl-5.12.3.0-portable/perl/site/lib   C​:/strawberry-perl-5.12.3.0-portable/perl/vendor/lib   C​:/strawberry-perl-5.12.3.0-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

Summary of my perl5 (revision 5 version 14 subversion 3) configuration​:  
  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x86-multi-thread   uname='Win32 strawberry-perl 5.14.3.1 #1 Wed Oct 17 22​:51​:55 2012 i386'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.14.3.1-32bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.14.3.1-32bit-portable\c\lib"'   libpth=C​:\strawberry-perl-5.14.3.1-32bit-portable\c\lib C​:\strawberry-perl-5.14.3.1-32bit-portable\c\i686-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl514.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.14.3.1-32bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.14.3.1-32bit-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_ITHREADS USE_LARGE_FILES USE_PERLIO   USE_PERL_ATOF   Built under MSWin32   Compiled at Oct 17 2012 23​:05​:06   @​INC​:   C​:/strawberry-perl-5.14.3.1-32bit-portable/perl/site/lib   C​:/strawberry-perl-5.14.3.1-32bit-portable/perl/vendor/lib   C​:/strawberry-perl-5.14.3.1-32bit-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

Summary of my perl5 (revision 5 version 14 subversion 3) configuration​:  
  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname='Win32 strawberry-perl 5.14.3.1 #1 Thu Oct 18 11​:28​:03 2012 x64'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.14.3.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.14.3.1-64bit-portable\c\lib"'   libpth=C​:\strawberry-perl-5.14.3.1-64bit-portable\c\lib C​:\strawberry-perl-5.14.3.1-64bit-portable\c\x86_64-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl514.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.14.3.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.14.3.1-64bit-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Oct 18 2012 11​:37​:31   @​INC​:   C​:/strawberry-perl-5.14.3.1-64bit-portable/perl/site/lib   C​:/strawberry-perl-5.14.3.1-64bit-portable/perl/vendor/lib   C​:/strawberry-perl-5.14.3.1-64bit-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

Summary of my perl5 (revision 5 version 16 subversion 1) configuration​:  
  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname='Win32 strawberry-perl 5.16.1.1 #1 Thu Aug 9 07​:49​:27 2012 x64'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.16.1.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.1.1-64bit-portable\c\lib"'   libpth=C​:\strawberry-perl-5.16.1.1-64bit-portable\c\lib C​:\strawberry-perl-5.16.1.1-64bit-portable\c\x86_64-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl516.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.16.1.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.1.1-64bit-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Aug 9 2012 07​:55​:51   @​INC​:   C​:/strawberry-perl-5.16.1.1-64bit-portable/perl/site/lib   C​:/strawberry-perl-5.16.1.1-64bit-portable/perl/vendor/lib   C​:/strawberry-perl-5.16.1.1-64bit-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:  
  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x86-multi-thread   uname='Win32 strawberry-perl 5.16.2.1 #1 Fri Nov 2 00​:33​:54 2012 i386'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.16.2.1-32bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.2.1-32bit-portable\c\lib"'   libpth=C​:\strawberry-perl-5.16.2.1-32bit-portable\c\lib C​:\strawberry-perl-5.16.2.1-32bit-portable\c\i686-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl516.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.16.2.1-32bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.2.1-32bit-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_ITHREADS USE_LARGE_FILES USE_LOCALE   USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Nov 2 2012 00​:44​:17   @​INC​:   C​:/strawberry-perl-5.16.2.1-32bit-portable/perl/site/lib   C​:/strawberry-perl-5.16.2.1-32bit-portable/perl/vendor/lib   C​:/strawberry-perl-5.16.2.1-32bit-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:  
  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname='Win32 strawberry-perl 5.16.2.1 #1 Fri Nov 2 03​:03​:35 2012 x64'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\strawberry-perl-5.16.2.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.2.1-64bit-portable\c\lib"'   libpth=C​:\strawberry-perl-5.16.2.1-64bit-portable\c\lib C​:\strawberry-perl-5.16.2.1-64bit-portable\c\x86_64-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl516.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\strawberry-perl-5.16.2.1-64bit-portable\perl\lib\CORE" -L"C​:\strawberry-perl-5.16.2.1-64bit-portable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Nov 2 2012 03​:12​:17   @​INC​:   C​:/strawberry-perl-5.16.2.1-64bit-portable/perl/site/lib   C​:/strawberry-perl-5.16.2.1-64bit-portable/perl/vendor/lib   C​:/strawberry-perl-5.16.2.1-64bit-portable/perl/lib   .


1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1' Taisha​:\~/perl/patches/badcarp $

p5pRT commented 11 years ago

From cm.perl@abtela.com

'\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable' CMD.EXE was started with the above path as the current directory. UNC paths are not supported. Defaulting to Windows directory.


Welcome to Strawberry Perl Portable Edition! * URL - http​://www.strawberryperl.com/ * see README.portable.TXT for more info


Perl executable​: \\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable\perl\bin\p erl.exe Perl version : 5.16.2 / MSWin32-x64-multi-thread

C​:\Windows>set ALLUSERSPROFILE=C​:\ProgramData APPDATA=C​:\Users\Administrator\AppData\Roaming CLIENTNAME=TAISHA CommonProgramFiles=C​:\Program Files\Common Files CommonProgramFiles(x86)=C​:\Program Files (x86)\Common Files CommonProgramW6432=C​:\Program Files\Common Files COMPUTERNAME=PRO-EDI ComSpec=C​:\Windows\system32\cmd.exe drive=\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable\ drivep=\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable FP_NO_HOST_CHECK=NO HOMEDRIVE=C​: HOMEPATH=\Users\Administrator LOCALAPPDATA=C​:\Users\Administrator\AppData\Local LOGONSERVER=\\PRO-EDI NUMBER_OF_PROCESSORS=2 OS=Windows_NT Path=\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable\perl\site\bin;\\tsclie nt\C\strawberry-perl-5.16.2.1-64bit-portable\perl\bin;\\tsclient\C\strawberry-pe rl-5.16.2.1-64bit-portable\c\bin;C​:\Windows\system32;C​:\Windows;C​:\Windows\Syste m32\Wbem;C​:\Windows\System32\WindowsPowerShell\v1.0\;C​:\Program Files\System Cen ter Operations Manager 2007\;C​:\Program Files (x86)\Microsoft SQL Server\100\Too ls\Binn\;D​:\Logiciels\SQL2008\100\Tools\Binn\;D​:\Logiciels\SQL2008\100\DTS\Binn\ ;C​:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\ ;C​:\Program Files (x86)\Microsoft SQL Server\100\DTS\Binn\ PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC PROCESSOR_ARCHITECTURE=AMD64 PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 26 Stepping 5\, GenuineIntel PROCESSOR_LEVEL=6 PROCESSOR_REVISION=1a05 ProgramData=C​:\ProgramData ProgramFiles=C​:\Program Files ProgramFiles(x86)=C​:\Program Files (x86) ProgramW6432=C​:\Program Files PROMPT=$P$G PSModulePath=C​:\Windows\system32\WindowsPowerShell\v1.0\Modules\ PUBLIC=C​:\Users\Public SESSIONNAME=RDP-Tcp#0 SystemDrive=C​: SystemRoot=C​:\Windows TEMP=C​:\Users\ADMINI~1\AppData\Local\Temp\2 TERM=dumb TMP=C​:\Users\ADMINI~1\AppData\Local\Temp\2 USERDOMAIN=PRO-EDI USERNAME=Administrator USERPROFILE=C​:\Users\Administrator windir=C​:\Windows windows_tracing_flags=3 windows_tracing_logfile=C​:\BVTBin\Tests\installpackage\csilogfile.log

C​:\Windows>perl -V Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:

  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname='Win32 strawberry-perl 5.16.2.1 #1 Fri Nov 2 03​:03​:35 2012 x64'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_ SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bi tfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"\\tsclient\C\strawberry-perl-5.16.2.1-64bit-po rtable\perl\lib\CORE" -L"\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable\c\ lib"'   libpth=\\tsclient\C\strawberry-perl-5.16.2.1-64bit-portable\c\lib \\tsclient \C\strawberry-perl-5.16.2.1-64bit-portable\c\x86_64-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladva pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lver sion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl516.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"\\tsclient\C\strawberry-perl-5.16.2.1 -64bit-portable\perl\lib\CORE" -L"\\tsclient\C\strawberry-perl-5.16.2.1-64bit-po rtable\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Nov 2 2012 03​:12​:17   @​INC​:   //tsclient/C/strawberry-perl-5.16.2.1-64bit-portable/perl/site/lib   //tsclient/C/strawberry-perl-5.16.2.1-64bit-portable/perl/vendor/lib   //tsclient/C/strawberry-perl-5.16.2.1-64bit-portable/perl/lib   .

C​:\Windows>type \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } }

C​:\Windows>perl \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl 1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at \\tsclient\E\cm\perl\patches\badcarp\onesubst.pl line 12. # got​: '0' # expected​: '1'

C​:\Windows>

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 18/12/2012 00​:35\, demerphq a écrit :

On 18 December 2012 00​:20\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

No\, sorry. What you want to say is /... unless they call a system call which fails/.

Hmm\, nope. What I mean\, and want to say\, is what I wrote.

Which is what happens here.

The regex engine may call out to disk to load code. This is a complex process which may involve any number of system calls setting $!.

I am well aware of that. However I don't see which this should be any concern of mine. In the future I might run a port of perl on the Santa computer\, whose CPU is actually a bunch of nimble-fingered dwarves\, and one of them might have to order a new abacus to carry on a request to compute 10+10. Should I be made aware\, even tangentially\, of all the transactions involved (or in reality\, only of the last one\, possibly the delivery notice of the brand new abacus) ? I don't think so\, at least not if those dwarves are able to perform the computation requested and return the result.

As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Umm again no. As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

That is the root of the problem. What you describe is indeed the behavior documented in perlvar. So\, if you need to preserve the value of $! (or $^E) across system calls\, you are supposed to take a copy and work with the copy. This is not always possible\, especially when you have to deal with opaque modules\, and I think it would be much cleaner if (some) subs did not trash $! and $^E if they do not use them to return a meaningful info to the calling code.

For a function that does not use $! or $^E to report errors\, the change in code is minimal\, something like sub safe_foo {   local ($!\, $^E);   goto unsafe_foo; } more realistically\, if a function might die/croak and need to report why through $! or $^E\, something like this would probably be better sub safe_foo {   my ($e\, $se) = ($!\, $^E);   my $ret = unsafe_foo(@​_);   ($!\, $^E) = ($e\, $se);   return $ret; }

High level programming is playing with trees. The current handling of $! and $^E is linear. The two paradigms do not mix well\, and the current state of affairs is IMHO less than satisfying. But if there is indeed any positive value to the current scheme please enlighten me.

Also\, if we are talking about system calls\, my understanding is that the proper level to report them is with $^E\, not $!\, but that is another debate.

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!.

Well\, IMO they should not.

I really wonder why. What useful purpose is served by allowing the trashing of $! and $^E ? On the other hand\, I do have a use for a clean croak/confess. I mostly write long-lived daemons or services\, which need to react intelligently to errors. For example\, a prototypical daemon in a processing pipeline might periodically fetch some data\, process them\, and push the result dowstream using a file copy. The copy might fail\, in which case the result is kept locally and the copy retried later. Depending on the nature of the error\, the daemon might attempt some corrective action : if it is a problem with space or quotas\, possibly cleanup some archives to get more space\, or mail or page the sysadmins to make room; if it is a problem with permissions\, mail the appadmin to fix the configuration or the sysadmins to ask them to stop playing god with ACLs and permissions; if it seems to be a temporary network outage\, bide our time; etc.

So the program needs to get a good idea of what the actual error is. Unfortunately\, if it comes from an opaque module croaking 'helfully' as in   croak "oops​: $!\, $^E" what you get is a string whose contents might depend on the version of the module\, the execution locale\, and whatnot... This is simply impossible to test reliably.

What are needed instead are numerical comparisons\, as in eval {   foo(...) }; if ($@​) {   my ($e\, $se) = ($!\, $^E);   if ($e == ENOSPC) { ... }   elsif ($e == EACCES) { ... }   ... }

But obviously it is then vital that croak/confess do not clobber $! and $^E...

It tests it badly\, as it turns out\, on MSWin32\,

This is only tangentally related to Win32. It has to do with the regex encountering unicode and calling out to disk to load unicode data.

Well IMHO it is related to Win32\, in that the test succeeds on unices and fails on Win32. BTW\, the test also fails with croak(qq{Dead\n})\, so it is not obviously a unicode issue. Also if it were a problem of calling files from disk I'd expect the results to be cached\, in which case the second of two consecutive tests would succeed\, which is not the case :

Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl -V Summary of my perl5 (revision 5 version 17 subversion 7) configuration​:   Derived from​:   Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++'\, ldflags ='-s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"'   libpth=C​:\MinGW\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl517.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE   PERL_PRESERVE_IVUV USE_64_BIT_INT USE_ITHREADS   USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE   USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO   USE_PERL_ATOF   Locally applied patches​:   uncommitted-changes   Built under MSWin32   Compiled at Dec 17 2012 13​:09​:34   @​INC​:   D​:/perl/site/lib   D​:/perl/lib   . Taisha​:\~/perl/patches/badcarp $ cat clobberingcroak.pl use warnings; use strict; use Carp; use Test​::More tests => 2; for (1 .. 2) {   local $! = my $arbitrary = 1;   eval {   croak "Dead\n";   };   if ($@​) {   my $err = 0+$!;   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'croak does not clobber $!');   }   } } Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl clobberingcroak.pl 1..2 not ok 1 - croak does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'croak does not clobber $!' # at clobberingcroak.pl line 14. # got​: '0' # expected​: '1' not ok 2 - croak does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'croak does not clobber $!' # at clobberingcroak.pl line 14. # got​: '0' # expected​: '1' Taisha​:\~/perl/patches/badcarp $

as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

If we are already trying hard not to change $! in croak then we should fix this behaviour. But I maintain it is not a bug. Or at least\, if it is a bug it is not that the regex engine might call out to disk.

I agree with the latter. However the client code should be isolated from the fact that the regex engine might call to disk. IMHO this is a fundamental tenet of abstraction and modular programming.

Yves

p5pRT commented 11 years ago

From @druud62

On 2012-12-28 17​:21\, Christian Millour wrote​:

Le 18/12/2012 00​:35\, demerphq a écrit​:

[...] As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

That is the root of the problem. What you describe is indeed the behavior documented in perlvar. So\, if you need to preserve the value of $! (or $^E) across system calls\, you are supposed to take a copy and work with the copy. This is not always possible\, especially when you have to deal with opaque modules\, and I think it would be much cleaner if (some) subs did not trash $! and $^E if they do not use them to return a meaningful info to the calling code.

Already forever\, the proposed alternative is to stack them\, like in @​! and @​@​ and such. That was never implemented\, so how big is the need really?

What are needed instead are numerical comparisons\, as in eval { foo(...) }; if ($@​) { my ($e\, $se) = ($!\, $^E); if ($e == ENOSPC) { ... } elsif ($e == EACCES) { ... } ... }

Why is that not using the return value of eval?

  eval {   foo(...);   1; # success   }   or do {   my ($eval_error\, $e\, $se) = ($@​\, $!\, $^E);   $eval_error //= 'Zombie Error';   ...   };

-- Ruud

p5pRT commented 11 years ago

From @demerphq

On 28 December 2012 17​:21\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 18/12/2012 00​:35\, demerphq a écrit :

On 18 December 2012 00​:20\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

No\, sorry. What you want to say is /... unless they call a system call which fails/.

Hmm\, nope. What I mean\, and want to say\, is what I wrote.

Well\, I'm sorry but then you are wrong. You cannot rely on $! being set to any given value except immediately after a failed system call. That is how ERRNO works in C\, and $! is a tie on ERRNO.

Which is what happens here.

The regex engine may call out to disk to load code. This is a complex process which may involve any number of system calls setting $!.

I am well aware of that. However I don't see which this should be any concern of mine. In the future I might run a port of perl on the Santa computer\, whose CPU is actually a bunch of nimble-fingered dwarves\, and one of them might have to order a new abacus to carry on a request to compute 10+10. Should I be made aware\, even tangentially\, of all the transactions involved (or in reality\, only of the last one\, possibly the delivery notice of the brand new abacus) ? I don't think so\, at least not if those dwarves are able to perform the computation requested and return the result.

Er\, what does this have to do with ERRNO being a global?

As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Umm again no. As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

That is the root of the problem. What you describe is indeed the behavior documented in perlvar. So\, if you need to preserve the value of $! (or $^E) across system calls\, you are supposed to take a copy and work with the copy. This is not always possible\, especially when you have to deal with opaque modules\,

Then in principle you should take it up with the authors of the modules.

and I think it would be much cleaner if (some) subs did not trash $! and $^E if they do not use them to return a meaningful info to the calling code.

In the sense of "would be nice if"\, not in the sense of "must happen".

For a function that does not use $! or $^E to report errors\, the change in code is minimal\, something like sub safe_foo { local ($!\, $^E); goto unsafe_foo; } more realistically\, if a function might die/croak and need to report why through $! or $^E\,

Sorry?

something like this would probably be better sub safe_foo { my ($e\, $se) = ($!\, $^E); my $ret = unsafe_foo(@​_); ($!\, $^E) = ($e\, $se); return $ret; }

High level programming is playing with trees. The current handling of $! and $^E is linear. The two paradigms do not mix well\, and the current state of affairs is IMHO less than satisfying. But if there is indeed any positive value to the current scheme please enlighten me.

It is ancient C behavior.

Also\, if we are talking about system calls\, my understanding is that the proper level to report them is with $^E\, not $!\, but that is another debate.

Setting $! is IMO unorthodox.

Here is the definition of $! from perlvar​:

  $ERRNO   $! If used numerically\, yields the current value of the C "errno" variable\, or in other words\, if a system or library call fails\, it   sets this variable. This means that the value of $! is meaningful only immediately after a failure​:

  if (open my $fh\, "\<"\, $filename) {   # Here $! is meaningless.   ...   } else {   # ONLY here is $! meaningful.   ...   # Already here $! might be meaningless.   }   # Since here we might have either success or failure\,   # here $! is meaningless.

  In the above meaningless stands for anything​: zero\, non-zero\, "undef". A successful system or library call does not set the   variable to zero.

  If used as a string\, yields the corresponding system error string. You can assign a number to $! to set errno if\, for instance\,   you want "$!" to return the string for error n\, or you want to set the exit value for the die() operator. (Mnemonic​: What just   went bang?)

  Also see "Error Indicators".

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!.

Well\, IMO they should not.

I really wonder why.

Because they are testing for something that fundamentally does not make sense to test for.

For instance\, it is quite legitimate that a croak() (which prints to STDERR) would set $! to something if STERR were closed.

I think there are a host of ways that ERRNO can be set\, and I dont think we can provide a guarantee that perl and croak() will not trigger one off them while executing.

What useful purpose is served by allowing the trashing of $! and $^E ?

It is not nice\, but that is how the underlying C code works.

On the other hand\, I do have a use for a clean croak/confess. I mostly write long-lived daemons or services\, which need to react intelligently to errors. For example\, a prototypical daemon in a processing pipeline might periodically fetch some data\, process them\, and push the result dowstream using a file copy. The copy might fail\, in which case the result is kept locally and the copy retried later. Depending on the nature of the error\, the daemon might attempt some corrective action : if it is a problem with space or quotas\, possibly cleanup some archives to get more space\, or mail or page the sysadmins to make room; if it is a problem with permissions\, mail the appadmin to fix the configuration or the sysadmins to ask them to stop playing god with ACLs and permissions; if it seems to be a temporary network outage\, bide our time; etc.

Ok.

So the program needs to get a good idea of what the actual error is. Unfortunately\, if it comes from an opaque module croaking 'helfully' as in croak "oops​: $!\, $^E" what you get is a string whose contents might depend on the version of the module\, the execution locale\, and whatnot... This is simply impossible to test reliably.

So again in principle you should speak to the author.

What are needed instead are numerical comparisons\, as in eval { foo(...) }; if ($@​) { my ($e\, $se) = ($!\, $^E); if ($e == ENOSPC) { ... } elsif ($e == EACCES) { ... } ... }

But obviously it is then vital that croak/confess do not clobber $! and $^E...

To me at this point you cannot trust $! nor $^E. Sorry\, but that is how it goes.

It tests it badly\, as it turns out\, on MSWin32\,

I can imagine. I can imagine this failing under all kinds of situations.

This is only tangentally related to Win32. It has to do with the regex encountering unicode and calling out to disk to load unicode data.

Well IMHO it is related to Win32\, in that the test succeeds on unices and fails on Win32.

Ok. I still think it is an artifact of the regex engine loading reference data.

BTW\, the test also fails with croak(qq{Dead\n})\, so it is not obviously a unicode issue. Also if it were a problem of calling files from disk I'd expect the results to be cached\, in which case the second of two consecutive tests would succeed\, which is not the case :

This could be a bug in the regex caching code.

Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl -V

Summary of my perl5 (revision 5 version 17 subversion 7) configuration​: Derived from​: Platform​: osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread uname='' config_args='undef' hint=recommended\, useposix=true\, d_sigaction=undef useithreads=define\, usemultiplicity=define useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef use64bitint=define\, use64bitall=undef\, uselongdouble=undef usemymalloc=n\, bincompat5005=undef Compiler​: cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\, optimize='-s -O2'\, cppflags='-DWIN32' ccversion=''\, gccversion='4.6.3'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8 alignbytes=8\, prototype=define Linker and Libraries​: ld='g++'\, ldflags ='-s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"' libpth=C​:\MinGW\lib libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 libc=\, so=dll\, useshrplib=true\, libperl=libperl517.a gnulibc_version='' Dynamic Linking​: dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags=' '\, lddlflags='-mdll -s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"'

Characteristics of this binary (from libperl)​: Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY PERLIO_LAYERS PERL_DONT_CREATE_GVSV PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF Locally applied patches​: uncommitted-changes Built under MSWin32 Compiled at Dec 17 2012 13​:09​:34 @​INC​:

D&#8203;:/perl/site/lib
D&#8203;:/perl/lib
\.

Taisha​:\~/perl/patches/badcarp $ cat clobberingcroak.pl use warnings; use strict; use Carp; use Test​::More tests => 2; for (1 .. 2) {

local $\! = my $arbitrary = 1;
eval \{
    croak "Dead\\n";
\};
if \($@&#8203;\) \{
    my $err = 0\+$\!;
  TODO&#8203;: \{

      local $TODO = "fails on $^O" if $^O eq 'MSWin32';
      is \($err\, $arbitrary\, 'croak does not clobber $\!'\);
    \}
\}

} Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl clobberingcroak.pl 1..2 not ok 1 - croak does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'croak does not clobber $!' # at clobberingcroak.pl line 14.

# got​: '0' # expected​: '1' not ok 2 - croak does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'croak does not clobber $!' # at clobberingcroak.pl line 14.

# got​: '0' # expected​: '1' Taisha​:\~/perl/patches/badcarp $

as the test would fail if the actual message contained any character matching ([[​:cntrl​:]]|[[​:^ascii​:]]). I did not think it necessary to report this or add a new test with for instance croak(q{Décédé}) instead of croak(q{Dead})\, because fixing #116118 will solve the problem directly.

If we are already trying hard not to change $! in croak then we should fix this behaviour. But I maintain it is not a bug. Or at least\, if it is a bug it is not that the regex engine might call out to disk.

I agree with the latter. However the client code should be isolated from the fact that the regex engine might call to disk. IMHO this is a fundamental tenet of abstraction and modular programming.

I still maintain that ultimately you have unreasonable expectations in this regard. ERRNO simply doesn't work like you seem to think it does.

The only time you can trust it is in code like this​:

if( ! system_call() ) { my $err_no= 0+$!; ny $err_str= "" . $!; report_error($errno\, $err_str); }

Any other use is suspect and pretty much guaranteed to be wrong.

Cheers\, yves -- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 11 years ago

From @bulk88

On Fri Dec 28 06​:02​:30 2012\, cm.perl@​abtela.com wrote​:

I am generally running Cygwin with strawberry perl portable (SPP) with no problem whatsoever\, provided I am careful with PATH. spp.log (attached) gives an example.

I have tried running a SPP portable window from an other machine (a fresh Windows Server 2008 R2 standard SP1\, without Cygwin) and get the error. See ts-spp.log (attached).

On this same machine I have installed Active State Perl and also get the error (see as.log\, attached).

If I am doing something wrong I really can't understand what it is. Could you please have a look at the attached logs and tell me what is amiss ?

Many thanks in advance\, and best regards

I still can't reproduce it. I also tried using UNC paths. Even though the @​INCs look fine in your 3 log posts. The file that is attached to this post was on a Server 2003 x64 machine. What I found interesting is\, on one of the logs\, it says "Microsoft Windows [Version 6.1.7601]"\, yet "osvers=5.2". That doesn't look right from a casual glance. Bug with Perl or what\, IDK. What I am trying to do is reproduce it\, so I can then try to trap access to MS CRT's errno (which is a function that returns an int * under the hood)\, and once its figured out what in perl is causing $! to change\, then the discussion of whether to fix it or not can take place. This report is getting derailed by hypothetical discussion\, when it doesn't fail on unix anyway (according to other posts in this thread)\, and nobody has identified what Win32 C C-lib call caused C errno to be changed. I don't think anyone yet in this ticket has claimed to reproduce the failure other than the reporter.

I've avoided any discussion on standards until now. If I understand the claims about $! and POSIX standard quotes correctly\, they can be taken mean that literally "$errno = $!;" would never ever work in Perl lang and that is a "wont fix - by design"\, because pp_gvsv or pp_padsv or pp_sassign made a call to malloc (pp_gvgv->Perl_stack_grow->Perl_av_extend->Perl_av_extend_guts->Perl_safesysfree->...->free) or memmove or some other call that "undefined" errno before Perl_magic_get would be eventually called. I will quote "The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value."\, and also from linux "a function that succeeds is allowed to change errno".

I am going to pull at straws on possible causes now

-something to do with msvcrt.dll on NT 6\, ActivePerl and Strawberry Perl use msvcrt.dll on 32 and 64 Windows. Most personal Visual C builds use a msvcr##.dll. msvcr##.dlls are not OS specific\, msvcrt.dll is OS specific AFAIK. I do not have any NT 6 machines\, can someone with Perl on NT 6 test the test script please?

-PATH problems\, 2 Perls in %PATH%\, you were calling the perls with an absolute path\, not a %PATH% lookup\, @​INC looks okay to my eyes\, but I dont know the details of the @​INC algorithm on Win32 Perl

-UNC problems\, I tried a loopback UNC path\, IDK if your //tsclient is going over a LAN or is just loopback and the test was on run PC tsclient

-virus or antivirus scanner/DLL injection hooking the CRT\, Win32/Kernel32\, or ntdll syscalls (Nt*())

I think I will try a procmon log of running the test script and see what disk access\, if any\, the perl process actually does while running the test script and the substitution operator.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @bulk88


Perl executable​: C​:\sperl\51621port\perl\bin\perl.exe Perl version : 5.16.2 / MSWin32-x64-multi-thread

C​:\sperl\51621port>cd C​:\Documents and Settings\Administrator\Desktop\

C​:\Documents and Settings\Administrator\Desktop>perl n1.pl 1..2 ok 1 - exactly one substitution performed ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Administrator\Desktop>perl -V Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:

  Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname='Win32 strawberry-perl 5.16.2.1 #1 Fri Nov 2 03​:03​:35 2012 x64'   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_ SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bi tfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++.exe'\, ldflags ='-s -L"C​:\sperl\51621port\perl\lib\CORE" -L"C​:\sperl\ 51621port\c\lib"'   libpth=C​:\sperl\51621port\c\lib C​:\sperl\51621port\c\x86_64-w64-mingw32\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladva pi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lver sion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl516.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"C​:\sperl\51621port\perl\lib\CORE" -L" C​:\sperl\51621port\c\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   Built under MSWin32   Compiled at Nov 2 2012 03​:12​:17   @​INC​:   C​:/sperl/51621port/perl/site/lib   C​:/sperl/51621port/perl/vendor/lib   C​:/sperl/51621port/perl/lib   .

C​:\Documents and Settings\Administrator\Desktop>type C​:\Documents and Settings\A dministrator\Desktop\n1.pl The system cannot find the file specified. Error occurred while processing​: C​:\Documents. The system cannot find the file specified. Error occurred while processing​: and. The system cannot find the path specified.

C​:\Documents and Settings\Administrator\Desktop>type "C​:\Documents and Settings\ Administrator\Desktop\n1.pl" use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } }

C​:\Documents and Settings\Administrator\Desktop>perl -w "\\dl585\C\Documents and Settings\Administrator\Desktop\n1.pl" 1..2 ok 1 - exactly one substitution performed ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32

C​:\Documents and Settings\Administrator\Desktop>

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 28/12/2012 18​:09\, demerphq a écrit :

On 28 December 2012 17​:21\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 18/12/2012 00​:35\, demerphq a écrit :

On 18 December 2012 00​:20\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

No\, sorry. What you want to say is /... unless they call a system call which fails/.

Hmm\, nope. What I mean\, and want to say\, is what I wrote.

Well\, I'm sorry but then you are wrong. You cannot rely on $! being set to any given value except immediately after a failed system call. That is how ERRNO works in C\, and $! is a tie on ERRNO.

Which is what happens here.

The regex engine may call out to disk to load code. This is a complex process which may involve any number of system calls setting $!.

I am well aware of that. However I don't see which this should be any concern of mine. In the future I might run a port of perl on the Santa computer\, whose CPU is actually a bunch of nimble-fingered dwarves\, and one of them might have to order a new abacus to carry on a request to compute 10+10. Should I be made aware\, even tangentially\, of all the transactions involved (or in reality\, only of the last one\, possibly the delivery notice of the brand new abacus) ? I don't think so\, at least not if those dwarves are able to perform the computation requested and return the result.

Er\, what does this have to do with ERRNO being a global?

As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Umm again no. As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

That is the root of the problem. What you describe is indeed the behavior documented in perlvar. So\, if you need to preserve the value of $! (or $^E) across system calls\, you are supposed to take a copy and work with the copy. This is not always possible\, especially when you have to deal with opaque modules\,

Then in principle you should take it up with the authors of the modules.

and when the problem lies with core functions ? See below.

and I think it would be much cleaner if (some) subs did not trash $! and $^E if they do not use them to return a meaningful info to the calling code.

In the sense of "would be nice if"\, not in the sense of "must happen".

let's discuss it\, why don't we ?

Actually\, I don't care that much :-) For years I have been working with home-patched perls and core/cpan modules. I thought I might give something back and take the time and efforts to try and have those (IMHO) useful mods make it to core\, but I don't need them.

For a function that does not use $! or $^E to report errors\, the change in code is minimal\, something like sub safe_foo { local ($!\, $^E); goto unsafe_foo; } more realistically\, if a function might die/croak and need to report why through $! or $^E\,

Sorry?

a contrived but simple example :

consider require\, and a program that might want to react smartly to a failure rather than simply exiting ; require dies on error. It does so with an occasionally less than useful message\, as the following demonstates :

[cm@​COS63 ~/badcarp]$ cat badrequire.pl use strict; use warnings; eval {   require DoesNotExist;   1; } or do {   my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E);   print   '$@​ : '\, $evalerr\, "\n"\,   '$! : '\, $e+0\, " ($e)\n"\,   '$^E​: '\, $se+0\, " ($se)\n"; }; eval {   require NotReadable;   1; } or do {   my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E);   print   '$@​ : '\, $evalerr\, "\n"\,   '$! : '\, $e+0\, " ($e)\n"\,   '$^E​: '\, $se+0\, " ($se)\n"; }; [cm@​COS63 ~/badcarp]$ perl badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (you may need to install the DoesNotExist module) (@​INC contains​: /home/cm/blead/perl/lib/site_perl/5.17.7/x86_64-linux /home/cm/blead/perl/lib/site_perl/5.17.7 /home/cm/blead/perl/lib/5.17.7/x86_64-linux /home/cm/blead/perl/lib/5.17.7 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm​: Permission denied at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$

(as their names indicate\, DoesNotExist.pm does not exist\, and NotReadable.pm exists but is not readable by the perl process; the first run is the system perl v5.10.1\, the second is blead. Both on Linux COS63 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12​:19​:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux).

Even though the message is somewhat better with blead\, the easiest\, safest\, version-resilient\, in fact the only tractable way to react adequately to the error is to test the numerical value of $!.

The problem with the messages from die/croak is that even though they may use the string value of $!\, they usually lose the dual nature of $!\, which makes error handling much harder than necessary (is at all feasible). An other problem of course is that the message structure may vary from one version of Perl to the other (not to mention the execution locale).

My reference to a function that "might die/croak and need to report why through $! or $^E" was admitedly unclear. I hope the above clarifies the problem : to die or croak is useful to raise an error\, but unless you die with a rich exception object\, you will often need uncorrupted $! and $^E to perform any useful error handling.

...

Also\, if we are talking about system calls\, my understanding is that the proper level to report them is with $^E\, not $!\, but that is another debate.

Setting $! is IMO unorthodox.

That is your opinion. Mine differs. And I would very much like an arbitration on this. But let us not digress. I will start an other thread on this.

Here is the definition of $! from perlvar​:

    $ERRNO
    $\!      If used numerically\, yields the current value of the C

"errno" variable\, or in other words\, if a system or library call fails\, it sets this variable. This means that the value of $! is meaningful only immediately after a failure​:

                if \(open my $fh\, "\<"\, $filename\) \{
                    \# Here $\! is meaningless\.
                    \.\.\.
                \} else \{
                    \# ONLY here is $\! meaningful\.
                    \.\.\.
                    \# Already here $\! might be meaningless\.
                \}
                \# Since here we might have either success or failure\,
                \# here $\! is meaningless\.

            In the above meaningless stands for anything&#8203;: zero\,

non-zero\, "undef". A successful system or library call does not set the variable to zero.

            If used as a string\, yields the corresponding system

error string. You can assign a number to $! to set errno if\, for instance\, you want "$!" to return the string for error n\, or you want to set the exit value for the die() operator. (Mnemonic​: What just went bang?)

            Also see "Error Indicators"\.

yes yes yes. I have known it by heart for the last ten years or so and to me it is as bogus now as it was when I first read it.

As a user of Perl I want $! and $^E to be useable. Maybe as a Perl core developer you are satisfied with tieing $! to errno and be done with it but IMHO this is a case of misplaced lazyness ;-) [take this with a pinch of salt : I don't understand enough of perl internals to have an informed view of the possible implementation\, and I have the utmost respect for the perl developers].

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!.

Well\, IMO they should not.

I really wonder why.

Because they are testing for something that fundamentally does not make sense to test for.

For instance\, it is quite legitimate that a croak() (which prints to STDERR) would set $! to something if STERR were closed.

hmmm. croak only prints to STDERR if you let it do so. In most error-handling cases the call will be wrapped in an eval block. But I agree in principle.

I think there are a host of ways that ERRNO can be set\, and I dont think we can provide a guarantee that perl and croak() will not trigger one off them while executing.

What useful purpose is served by allowing the trashing of $! and $^E ?

It is not nice\, but that is how the underlying C code works.

Well\, it is maybe how the current implementation of $! works. Even if we do not change it I think it might be possible to obtain a consensus on the fact that it would be useful if some functions made an effort not to clobber $! and $^E if they don't have to. For instance I have patched a workable carp and family simply by localizing $! and $^E around the call to the subst mentioned in the original post. Also\, I believe that require should really behave as follows (pseudocode) : sub require {   my ($e\, $se) = ($!\, $^E);   my $ret = ... current code ...   ($!\, $^E) = ($e\, $se)   return $ret; } see why at the end of this message.

On the other hand\, I do have a use for a clean croak/confess. I mostly write long-lived daemons or services\, which need to react intelligently to errors. For example\, a prototypical daemon in a processing pipeline might periodically fetch some data\, process them\, and push the result dowstream using a file copy. The copy might fail\, in which case the result is kept locally and the copy retried later. Depending on the nature of the error\, the daemon might attempt some corrective action : if it is a problem with space or quotas\, possibly cleanup some archives to get more space\, or mail or page the sysadmins to make room; if it is a problem with permissions\, mail the appadmin to fix the configuration or the sysadmins to ask them to stop playing god with ACLs and permissions; if it seems to be a temporary network outage\, bide our time; etc.

Ok.

So the program needs to get a good idea of what the actual error is. Unfortunately\, if it comes from an opaque module croaking 'helfully' as in croak "oops​: $!\, $^E" what you get is a string whose contents might depend on the version of the module\, the execution locale\, and whatnot... This is simply impossible to test reliably.

So again in principle you should speak to the author.

in practice\, since having croak and family respect $! and $^E is much more practical and easier (I routinely patch them for my own production work)\, I prefer the latter ;-)

What are needed instead are numerical comparisons\, as in eval { foo(...) }; if ($@​) { my ($e\, $se) = ($!\, $^E); if ($e == ENOSPC) { ... } elsif ($e == EACCES) { ... } ... }

But obviously it is then vital that croak/confess do not clobber $! and $^E...

To me at this point you cannot trust $! nor $^E. Sorry\, but that is how it goes.

It means you have no tractable way to handle errors. Not good enough for production work.

If we are already trying hard not to change $! in croak then we should fix this behaviour. But I maintain it is not a bug. Or at least\, if it is a bug it is not that the regex engine might call out to disk.

I agree with the latter. However the client code should be isolated from the fact that the regex engine might call to disk. IMHO this is a fundamental tenet of abstraction and modular programming.

I still maintain that ultimately you have unreasonable expectations in this regard. ERRNO simply doesn't work like you seem to think it does.

The current tie between errno and $! is an implementation detail that might be changed and need not constrain (y)our thinking.

If your only use of Perl is within a US-English localized unix\, then your view might be adequate. But it is a large world and there are ports around\, among them VMS and Win32\, and if I read correctly a port for Android is in progress. From my (admitely limited) understanding\, on VMS and Win32\, $! is only remotely related to the system errno.

The only time you can trust it is in code like this​:

if( ! system_call() ) { my $err_no= 0+$!; ny $err_str= "" . $!; report_error($errno\, $err_str); }

Any other use is suspect and pretty much guaranteed to be wrong.

which makes for nasty traps\, even with longstanding\, core-sanctioned idoms such as the defered loading of carp and family :

[cm@​COS63 ~/badcarp]$ cat deferedcroak.pl use strict; use warnings; use Test​::More tests => 1; sub croak {   # warn 'before require\, $! = '\, 0+$!\, ' ('\, $!\, ')';   require Carp;   # warn 'after require\, $! = '\, 0+$!\, ' ('\, $!\, ')';   goto &Carp​::carp; }

{   local $! = 1;   my $expect = "$!";   my $actual = "unset!";   eval {   croak $!;   };   if (my $e = $@​) {   $actual = $e;   }   is ($actual\, $expect\, "'$actual' is '$expect' as expected"); } [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 deferedcroak.pl 1..1   at deferedcroak.pl line 16.   eval {...} called at deferedcroak.pl line 15 not ok 1 - 'unset!' is 'Operation not permitted' as expected # Failed test ''unset!' is 'Operation not permitted' as expected' # at deferedcroak.pl line 21. # got​: 'unset!' # expected​: 'Operation not permitted' # Looks like you failed 1 test of 1. [cm@​COS63 ~/badcarp]$

The problem here of course is that require clobbers $! when successful\, when it should leave it well alone. I was planning to send it as a bug report cum TODO test but it does not seem to be worth the trouble if it gets also qualified as notabug.

Cheers\, yves

Regards\,

Christian.

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 28/12/2012 22​:26\, Christian Millour a écrit :

Le 28/12/2012 18​:09\, demerphq a écrit :

On 28 December 2012 17​:21\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 18/12/2012 00​:35\, demerphq a écrit :

On 18 December 2012 00​:20\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Le 17/12/2012 20​:59\, demerphq a écrit :

successful substitutions with s///e clobber $! on MSWin32. See attached patch for a sample test case.

One impact of this bug is that\, because such a substitution occurs in Carp​::format_args\, specifically $arg =~ s/([[​:cntrl​:]]|[[​:^ascii​:]])/sprintf("\\x{%x}"\,ord($1))/eg; carp and family in turn sometimes clobber $! on MSWin32\, which may make debugging much harder than necessary.

$! is only valid _immediately_ after a failed system call.

If you use $! after you have done a carp() then you have waited too long.

If your problem is that you are doing carp("dollar-bang is "\, $!) you should just change it to "dollar-bang is $!"

So\, IMO this is not a bug.

I beg to disagree ; carp and family have no business altering $! (or $^E for that matter)\, unless they themselves fail.

No\, sorry. What you want to say is /... unless they call a system call which fails/.

Hmm\, nope. What I mean\, and want to say\, is what I wrote.

Well\, I'm sorry but then you are wrong. You cannot rely on $! being set to any given value except immediately after a failed system call. That is how ERRNO works in C\, and $! is a tie on ERRNO.

Which is what happens here.

The regex engine may call out to disk to load code. This is a complex process which may involve any number of system calls setting $!.

I am well aware of that. However I don't see which this should be any concern of mine. In the future I might run a port of perl on the Santa computer\, whose CPU is actually a bunch of nimble-fingered dwarves\, and one of them might have to order a new abacus to carry on a request to compute 10+10. Should I be made aware\, even tangentially\, of all the transactions involved (or in reality\, only of the last one\, possibly the delivery notice of the brand new abacus) ? I don't think so\, at least not if those dwarves are able to perform the computation requested and return the result.

Er\, what does this have to do with ERRNO being a global?

As a reporting mechanism they should not alter the observed phenomenon\, quantum perl theory notwithstanding ;-)

Umm again no. As soon as you call any operation that might make a system call the value of $! becomes undefined\, unless that system call returns false.

That is the root of the problem. What you describe is indeed the behavior documented in perlvar. So\, if you need to preserve the value of $! (or $^E) across system calls\, you are supposed to take a copy and work with the copy. This is not always possible\, especially when you have to deal with opaque modules\,

Then in principle you should take it up with the authors of the modules.

and when the problem lies with core functions ? See below.

and I think it would be much cleaner if (some) subs did not trash $! and $^E if they do not use them to return a meaningful info to the calling code.

In the sense of "would be nice if"\, not in the sense of "must happen".

let's discuss it\, why don't we ?

Actually\, I don't care that much :-) For years I have been working with home-patched perls and core/cpan modules. I thought I might give something back and take the time and efforts to try and have those (IMHO) useful mods make it to core\, but I don't need them.

For a function that does not use $! or $^E to report errors\, the change in code is minimal\, something like sub safe_foo { local ($!\, $^E); goto unsafe_foo; } more realistically\, if a function might die/croak and need to report why through $! or $^E\,

Sorry?

a contrived but simple example :

consider require\, and a program that might want to react smartly to a failure rather than simply exiting ; require dies on error. It does so with an occasionally less than useful message\, as the following demonstates :

[cm@​COS63 ~/badcarp]$ cat badrequire.pl use strict; use warnings; eval { require DoesNotExist; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; eval { require NotReadable; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; [cm@​COS63 ~/badcarp]$ perl badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (you may need to install the DoesNotExist module) (@​INC contains​: /home/cm/blead/perl/lib/site_perl/5.17.7/x86_64-linux /home/cm/blead/perl/lib/site_perl/5.17.7 /home/cm/blead/perl/lib/5.17.7/x86_64-linux /home/cm/blead/perl/lib/5.17.7 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm​: Permission denied at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$

(as their names indicate\, DoesNotExist.pm does not exist\, and NotReadable.pm exists but is not readable by the perl process; the first run is the system perl v5.10.1\, the second is blead. Both on Linux COS63 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12​:19​:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux).

Even though the message is somewhat better with blead\, the easiest\, safest\, version-resilient\, in fact the only tractable way to react adequately to the error is to test the numerical value of $!.

The problem with the messages from die/croak is that even though they may use the string value of $!\, they usually lose the dual nature of $!\, which makes error handling much harder than necessary (is at all feasible). An other problem of course is that the message structure may vary from one version of Perl to the other (not to mention the execution locale).

My reference to a function that "might die/croak and need to report why through $! or $^E" was admitedly unclear. I hope the above clarifies the problem : to die or croak is useful to raise an error\, but unless you die with a rich exception object\, you will often need uncorrupted $! and $^E to perform any useful error handling.

...

Also\, if we are talking about system calls\, my understanding is that the proper level to report them is with $^E\, not $!\, but that is another debate.

Setting $! is IMO unorthodox.

That is your opinion. Mine differs. And I would very much like an arbitration on this. But let us not digress. I will start an other thread on this.

Here is the definition of $! from perlvar​:

    $ERRNO
    $\!      If used numerically\, yields the current value of the C

"errno" variable\, or in other words\, if a system or library call fails\, it sets this variable. This means that the value of $! is meaningful only immediately after a failure​:

                if \(open my $fh\, "\<"\, $filename\) \{
                    \# Here $\! is meaningless\.
                    \.\.\.
                \} else \{
                    \# ONLY here is $\! meaningful\.
                    \.\.\.
                    \# Already here $\! might be meaningless\.
                \}
                \# Since here we might have either success or failure\,
                \# here $\! is meaningless\.

            In the above meaningless stands for anything&#8203;: zero\,

non-zero\, "undef". A successful system or library call does not set the variable to zero.

            If used as a string\, yields the corresponding system

error string. You can assign a number to $! to set errno if\, for instance\, you want "$!" to return the string for error n\, or you want to set the exit value for the die() operator. (Mnemonic​: What just went bang?)

            Also see "Error Indicators"\.

yes yes yes. I have known it by heart for the last ten years or so and to me it is as bogus now as it was when I first read it.

As a user of Perl I want $! and $^E to be useable. Maybe as a Perl core developer you are satisfied with tieing $! to errno and be done with it but IMHO this is a case of misplaced lazyness ;-) [take this with a pinch of salt : I don't understand enough of perl internals to have an informed view of the possible implementation\, and I have the utmost respect for the perl developers].

Note incidentally that dist/Carp/t/Carp.t explicitly checks that croak() and confess() don't clobber $!.

Well\, IMO they should not.

I really wonder why.

Because they are testing for something that fundamentally does not make sense to test for.

For instance\, it is quite legitimate that a croak() (which prints to STDERR) would set $! to something if STERR were closed.

hmmm. croak only prints to STDERR if you let it do so. In most error-handling cases the call will be wrapped in an eval block. But I agree in principle.

I think there are a host of ways that ERRNO can be set\, and I dont think we can provide a guarantee that perl and croak() will not trigger one off them while executing.

What useful purpose is served by allowing the trashing of $! and $^E ?

It is not nice\, but that is how the underlying C code works.

Well\, it is maybe how the current implementation of $! works. Even if we do not change it I think it might be possible to obtain a consensus on the fact that it would be useful if some functions made an effort not to clobber $! and $^E if they don't have to. For instance I have patched a workable carp and family simply by localizing $! and $^E around the call to the subst mentioned in the original post. Also\, I believe that require should really behave as follows (pseudocode) : sub require { my ($e\, $se) = ($!\, $^E); my $ret = ... current code ... ($!\, $^E) = ($e\, $se) return $ret; } see why at the end of this message.

On the other hand\, I do have a use for a clean croak/confess. I mostly write long-lived daemons or services\, which need to react intelligently to errors. For example\, a prototypical daemon in a processing pipeline might periodically fetch some data\, process them\, and push the result dowstream using a file copy. The copy might fail\, in which case the result is kept locally and the copy retried later. Depending on the nature of the error\, the daemon might attempt some corrective action : if it is a problem with space or quotas\, possibly cleanup some archives to get more space\, or mail or page the sysadmins to make room; if it is a problem with permissions\, mail the appadmin to fix the configuration or the sysadmins to ask them to stop playing god with ACLs and permissions; if it seems to be a temporary network outage\, bide our time; etc.

Ok.

So the program needs to get a good idea of what the actual error is. Unfortunately\, if it comes from an opaque module croaking 'helfully' as in croak "oops​: $!\, $^E" what you get is a string whose contents might depend on the version of the module\, the execution locale\, and whatnot... This is simply impossible to test reliably.

So again in principle you should speak to the author.

in practice\, since having croak and family respect $! and $^E is much more practical and easier (I routinely patch them for my own production work)\, I prefer the latter ;-)

What are needed instead are numerical comparisons\, as in eval { foo(...) }; if ($@​) { my ($e\, $se) = ($!\, $^E); if ($e == ENOSPC) { ... } elsif ($e == EACCES) { ... } ... }

But obviously it is then vital that croak/confess do not clobber $! and $^E...

To me at this point you cannot trust $! nor $^E. Sorry\, but that is how it goes.

It means you have no tractable way to handle errors. Not good enough for production work.

If we are already trying hard not to change $! in croak then we should fix this behaviour. But I maintain it is not a bug. Or at least\, if it is a bug it is not that the regex engine might call out to disk.

I agree with the latter. However the client code should be isolated from the fact that the regex engine might call to disk. IMHO this is a fundamental tenet of abstraction and modular programming.

I still maintain that ultimately you have unreasonable expectations in this regard. ERRNO simply doesn't work like you seem to think it does.

The current tie between errno and $! is an implementation detail that might be changed and need not constrain (y)our thinking.

If your only use of Perl is within a US-English localized unix\, then your view might be adequate. But it is a large world and there are ports around\, among them VMS and Win32\, and if I read correctly a port for Android is in progress. From my (admitely limited) understanding\, on VMS and Win32\, $! is only remotely related to the system errno.

The only time you can trust it is in code like this​:

if( ! system_call() ) { my $err_no= 0+$!; ny $err_str= "" . $!; report_error($errno\, $err_str); }

Any other use is suspect and pretty much guaranteed to be wrong.

which makes for nasty traps\, even with longstanding\, core-sanctioned idoms such as the defered loading of carp and family :

Ooops. I messed a paste. Please read instead

[cm@​COS63 ~/badcarp]$ cat deferedcarp.pl use strict; use warnings; use Test​::More tests => 2; sub carp {   # warn 'before require\, $! = '\, 0+$!\, ' ('\, $!\, ')';   require Carp;   # warn 'after require\, $! = '\, 0+$!\, ' ('\, $!\, ')';   goto &Carp​::carp; }

for (1 .. 2) {   local $! = 1;   my $expect = "$!";   my $actual = "unset!";   local $SIG{__WARN__} = sub { $actual = shift };   eval {   carp $!;   };   if (my $e = $@​) {   warn $e;   $actual = $1 if ($e =~ /^'(.*)' at /);   }   ok ($actual =~ qr/^$expect/\, "'$actual' starts with '$expect' as expected"); } [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 deferedcarp.pl 1..2 not ok 1 - ' at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected # Failed test '' at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected' # at deferedcarp.pl line 23. ok 2 - 'Operation not permitted at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected # Looks like you failed 1 test of 2. [cm@​COS63 ~/badcarp]$

The problem here of course is that require clobbers $! when successful\, when it should leave it well alone. I was planning to send it as a bug report cum TODO test but it does not seem to be worth the trouble if it gets also qualified as notabug.

Cheers\, yves

Regards\,

Christian.

p5pRT commented 11 years ago

From @Leont

On Fri\, Dec 28\, 2012 at 10​:53 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Ooops. I messed a paste. Please read instead

[cm@​COS63 ~/badcarp]$ cat deferedcarp.pl use strict; use warnings; use Test​::More tests => 2; sub carp {

\# warn 'before require\, $\! = '\, 0\+$\!\, ' \('\, $\!\, '\)';
require Carp;
\# warn 'after  require\, $\! = '\, 0\+$\!\, ' \('\, $\!\, '\)';
goto &Carp&#8203;::carp;

}

for (1 .. 2) {

local $\! = 1;
my $expect = "$\!";
my $actual = "unset\!";
local $SIG\{\_\_WARN\_\_\} = sub \{ $actual = shift \};
eval \{
    carp $\!;

\};
if \(my $e = $@&#8203;\) \{
    warn $e;
    $actual = $1 if \($e =~ /^'\(\.\*\)' at /\);
\}
ok \($actual =~ qr/^$expect/\, "'$actual' starts with '$expect' as

expected"); } [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 deferedcarp.pl 1..2 not ok 1 - ' at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected # Failed test '' at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected' # at deferedcarp.pl line 23. ok 2 - 'Operation not permitted at deferedcarp.pl line 17. # eval {...} called at deferedcarp.pl line 16 # ' starts with 'Operation not permitted' as expected

# Looks like you failed 1 test of 2. [cm@​COS63 ~/badcarp]$

That test starts passing when replacing «carp $!» with «carp "$!"». That's a very different kind of bug to me.

Leon

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 28/12/2012 19​:51\, bulk88 via RT a écrit :

On Fri Dec 28 06​:02​:30 2012\, cm.perl@​abtela.com wrote​:

I am generally running Cygwin with strawberry perl portable (SPP) with no problem whatsoever\, provided I am careful with PATH. spp.log (attached) gives an example.

I have tried running a SPP portable window from an other machine (a fresh Windows Server 2008 R2 standard SP1\, without Cygwin) and get the error. See ts-spp.log (attached).

On this same machine I have installed Active State Perl and also get the error (see as.log\, attached).

If I am doing something wrong I really can't understand what it is. Could you please have a look at the attached logs and tell me what is amiss ?

Many thanks in advance\, and best regards

I still can't reproduce it. I also tried using UNC paths. Even though the @​INCs look fine in your 3 log posts. The file that is attached to this post was on a Server 2003 x64 machine. What I found interesting is\, on one of the logs\, it says "Microsoft Windows [Version 6.1.7601]"\, yet "osvers=5.2". That doesn't look right from a casual glance. Bug with Perl or what\, IDK. What I am trying to do is reproduce it\, so I can then try to trap access to MS CRT's errno (which is a function that returns an int * under the hood)\, and once its figured out what in perl is causing $! to change\, then the discussion of whether to fix it or not can take place. This report is getting derailed by hypothetical discussion\, when it doesn't fail on unix anyway (according to other posts in this thread)\, and nobody has identified what Win32 C C-lib call caused C errno to be changed. I don't think anyone yet in this ticket has claimed to reproduce the failure other than the reporter.

I don't believe the problem lies with UNC paths. Here is activestate perl with a local file :

C​:\Users\Administrator>c​:\Perl64\bin\perl -V Summary of my perl5 (revision 5 version 16 subversion 1) configuration​:

  Platform​:   osname=MSWin32\, osvers=5.2\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -Ox -GL -fp​:precise -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -D USE_PERLIO'\,   optimize='-MD -Zi -DNDEBUG -Ox -GL -fp​:precise'\,   cppflags='-DWIN32'   ccversion='14.00.40310.41'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='__int64'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'   libpth=\lib   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib bufferoverflowU.lib msvcrt.lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32. lib comctl32.lib bufferoverflowU.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl516.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   USE_SITECUSTOMIZE   Locally applied patches​:   ActivePerl Build 1601 [296175]   Built under MSWin32   Compiled at Aug 30 2012 18​:41​:50   @​INC​:   c​:/Perl64/site/lib   c​:/Perl64/lib   .

C​:\Users\Administrator>type onesubst.pl use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } }

C​:\Users\Administrator>C​:\Perl64\bin\perl -w onesubst.pl 1..2 ok 1 - exactly one substitution performed not ok 2 - successful s///e does not clobber $! # TODO fails on MSWin32 # Failed (TODO) test 'successful s///e does not clobber $!' # at onesubst.pl line 12. # got​: '0' # expected​: '1'

C​:\Users\Administrator>

I've avoided any discussion on standards until now. If I understand the claims about $! and POSIX standard quotes correctly\, they can be taken mean that literally "$errno = $!;" would never ever work in Perl lang and that is a "wont fix - by design"\, because pp_gvsv or pp_padsv or pp_sassign made a call to malloc (pp_gvgv->Perl_stack_grow->Perl_av_extend->Perl_av_extend_guts->Perl_safesysfree->...->free) or memmove or some other call that "undefined" errno before Perl_magic_get would be eventually called. I will quote "The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value."\, and also from linux "a function that succeeds is allowed to change errno".

I am going to pull at straws on possible causes now

-something to do with msvcrt.dll on NT 6\, ActivePerl and Strawberry Perl use msvcrt.dll on 32 and 64 Windows. Most personal Visual C builds use a msvcr##.dll. msvcr##.dlls are not OS specific\, msvcrt.dll is OS specific AFAIK. I do not have any NT 6 machines\, can someone with Perl on NT 6 test the test script please?

-PATH problems\, 2 Perls in %PATH%\, you were calling the perls with an absolute path\, not a %PATH% lookup\, @​INC looks okay to my eyes\, but I dont know the details of the @​INC algorithm on Win32 Perl

-UNC problems\, I tried a loopback UNC path\, IDK if your //tsclient is going over a LAN or is just loopback and the test was on run PC tsclient

My standard workhorse is a Win7 box. The uses of //tsclient were from a Windows Server 2008 R2 SP1 run as a virtual machine from vmware server 2 running on the win7 box. I'll try again tomorrow on a different physical box.

-virus or antivirus scanner/DLL injection hooking the CRT\, Win32/Kernel32\, or ntdll syscalls (Nt*()) FWIW​: The Win7 box is running MicroSoft Security Essentials. The virtual machine is running Kasperky 8.0.0.559.

I think I will try a procmon log of running the test script and see what disk access\, if any\, the perl process actually does while running the test script and the substitution operator.

p5pRT commented 11 years ago

From @Leont

On Fri\, Dec 28\, 2012 at 10​:26 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

a contrived but simple example :

consider require\, and a program that might want to react smartly to a failure rather than simply exiting ; require dies on error. It does so with an occasionally less than useful message\, as the following demonstates :

[cm@​COS63 ~/badcarp]$ cat badrequire.pl use strict; use warnings; eval { require DoesNotExist; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; eval { require NotReadable; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; [cm@​COS63 ~/badcarp]$ perl badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (you may need to install the DoesNotExist module) (@​INC contains​: /home/cm/blead/perl/lib/site_perl/5.17.7/x86_64-linux /home/cm/blead/perl/lib/site_perl/5.17.7 /home/cm/blead/perl/lib/5.17.7/x86_64-linux /home/cm/blead/perl/lib/5.17.7 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm​: Permission denied at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$

(as their names indicate\, DoesNotExist.pm does not exist\, and NotReadable.pm exists but is not readable by the perl process; the first run is the system perl v5.10.1\, the second is blead. Both on Linux COS63 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12​:19​:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux).

Even though the message is somewhat better with blead\, the easiest\, safest\, version-resilient\, in fact the only tractable way to react adequately to the error is to test the numerical value of $!.

I'm not really seeing your point here.

The problem with the messages from die/croak is that even though they may use the string value of $!\, they usually lose the dual nature of $!\, which makes error handling much harder than necessary (is at all feasible). An other problem of course is that the message structure may vary from one version of Perl to the other (not to mention the execution locale).

My reference to a function that "might die/croak and need to report why through $! or $^E" was admitedly unclear. I hope the above clarifies the problem : to die or croak is useful to raise an error\, but unless you die with a rich exception object\, you will often need uncorrupted $! and $^E to perform any useful error handling.

Obviously this does not work in an optimal fashion\, but I don't think pimping up $! is the real solution for that. To the contrary\, it's making exceptions richer that is.

As a user of Perl I want $! and $^E to be useable. Maybe as a Perl core developer you are satisfied with tieing $! to errno and be done with it but IMHO this is a case of misplaced lazyness ;-) [take this with a pinch of salt : I don't understand enough of perl internals to have an informed view of the possible implementation\, and I have the utmost respect for the perl developers].

It's still not clear to me what other behavior you would want. It still sounds to me like you want a lollipop.

Well\, it is maybe how the current implementation of $! works. Even if we do not change it I think it might be possible to obtain a consensus on the fact that it would be useful if some functions made an effort not to clobber $! and $^E if they don't have to. For instance I have patched a workable carp and family simply by localizing $! and $^E around the call to the subst mentioned in the original post. Also\, I believe that require should really behave as follows (pseudocode) : sub require {

my ($e\, $se) = ($!\, $^E); my $ret = ... current code ...

($!\, $^E) = ($e\, $se) return $ret; }

That's a rather crude hack\, and I doubt that's the best solution in most cases.

in practice\, since having croak and family respect $! and $^E is much more practical and easier (I routinely patch them for my own production work)\, I prefer the latter ;-)

I think that what you really want here is that longmess and shortmess "respect" $! and $^E. Because AFAICT they don't really have any good reason to want to modify them. carp/croak/cluck/confess however do (or better said\, the die/warn in them do).

The current tie between errno and $! is an implementation detail that might be changed and need not constrain (y)our thinking.

Once again\, lollipops…

Leon

p5pRT commented 11 years ago

From @bulk88

On Fri Dec 28 10​:51​:02 2012\, bulk88 wrote​:

I think I will try a procmon log of running the test script and see what disk access\, if any\, the perl process actually does while running the test script and the substitution operator.

script run was __________________________________________________________________ use warnings; use strict; use Test​::More tests => 2; {   local $! = my $arbitrary = 1;   my $arg = "a";   sleep 5;   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } } __________________________________________________________________

the substitute line I think loaded overload.pm

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @bulk88

[116118 procmon.CSV](https://rt-archive.perl.org/perl5/Ticket/Attachment/1180868/606980/116118 procmon.CSV)

p5pRT commented 11 years ago

From @bulk88

On Fri Dec 28 15​:14​:54 2012\, bulk88 wrote​:

the substitute line I think loaded overload.pm

____________________________________________________________________

ntdll.dll!_KiFastSystemCall@​0() + 0x2
  ntdll.dll!_NtCreateFile@​44() + 0xc
  kernel32.dll!_CreateFileW@​28() + 0x1b6
  kernel32.dll!_CreateFileA@​28() + 0x2b
  msvcr71.dll!_tsopen_lk(int * punlock_flag=0x0012f800\, int * pfh=0x0012f7fc\, const char * path=0x00345a40\, int oflag=32768\, int shflag=1242824\, int pmode=438) Line 387 + 0x24 C   msvcr71.dll!_open(const char * path=0x00345a40\, int oflag=32768\, ...) Line 110 + 0x19 C   perl517.dll!win32_open(const char * path=0x0090243c\, int flag=32768\, ...) Line 3241 + 0x2c C   perl517.dll!PerlLIOOpen3(IPerlLIO * piPerl=0x003457a4\, const char * filename=0x0090243c\, int oflag=32768\, int pmode=438) Line 1026 + 0x11 C   perl517.dll!PerlIOUnix_open(interpreter * my_perl=0x00343e54\, _PerlIO_funcs * self=0x2819be28\, PerlIO_list_s * layers=0x009027c4\, long n=0\, const char * mode=0x28186344\, int fd=-1\, int imode=32768\, int perm=438\, _PerlIO * * f=0x00000000\, int narg=1\, sv * * args=0x0012f97c) Line 2716 + 0x22 C   perl517.dll!PerlIOBuf_open(interpreter * my_perl=0x00343e54\, _PerlIO_funcs * self=0x2819bfe8\, PerlIO_list_s * layers=0x009027c4\, long n=1\, const char * mode=0x28186344\, int fd=-1\, int imode=0\, int perm=0\, _PerlIO * * f=0x00000000\, int narg=1\, sv * * args=0x0012f97c) Line 3857 + 0x35 C   perl517.dll!PerlIO_openn(interpreter * my_perl=0x00343e54\, const char * layers=0x28181b68\, const char * mode=0x28186344\, int fd=-1\, int imode=0\, int perm=0\, _PerlIO * * f=0x00000000\, int narg=1\, sv * * args=0x0012f97c) Line 1648 + 0x32 C   perl517.dll!S_check_type_and_open(interpreter * my_perl=0x00343e54\, sv * name=0x00a3a49c) Line 3551 + 0x21 C   perl517.dll!S_doopen_pm(interpreter * my_perl=0x00343e54\, sv * name=0x00a3a49c) Line 3576 + 0xd C   perl517.dll!Perl_pp_require(interpreter * my_perl=0x00343e54) Line 3901 + 0xd C   perl517.dll!Perl_runops_standard(interpreter * my_perl=0x00343e54) Line 42 + 0xa C   perl517.dll!S_run_body(interpreter * my_perl=0x00343e54\, long oldscope=1) Line 2430 + 0xd C   perl517.dll!perl_run(interpreter * my_perl=0x00343e54) Line 2349 C   perl517.dll!RunPerl(int argc=2\, char * * argv=0x00343da8\, char * * env=0x00344e00) Line 270 + 0x9 C   perl.exe!mainCRTStartup() Line 398 + 0xe C   kernel32.dll!_BaseProcessStart@​4() + 0x23
____________________________________________________________________ A concise dump isn't showing the pp_require.

____________________________________________________________________ B​::Concise​::compile(CODE(0xdd82ac)) # 18​: local $! = my $arbitrary = 1; 1 \<;> dbstate(main -8 C​:\Documents and Settings\Owner\Desktop\n11.pl​:18) v​:*\,&\,{\,x*\,x&\,x$\,$ 2 \<$> const[IV 1] s 3 \<0> padsv[$arbitrary​:-8\,-2] sRM*/LVINTRO 4 \<2> sassign sKS/2 5 \<#> gvsv[*!] s/LVINTRO 6 \<2> sassign vKS/2 # 19​: my $arg = "a"; 7 \<;> dbstate(main -7 C​:\Documents and Settings\Owner\Desktop\n11.pl​:19) v​:*\,&\,{\,x*\,x&\,x$\,$ 8 \<$> const[PV "a"] s 9 \<0> padsv[$arg​:-7\,-2] sRM*/LVINTRO a \<2> sassign vKS/2 # 20​: system("pause"); b \<;> dbstate(main -6 C​:\Documents and Settings\Owner\Desktop\n11.pl​:20) v​:*\,&\,{\,x*\,x&\,x$\,$ c \<0> pushmark s d \<$> const[PV "pause"] s e \<@​> system[t4] vK # 21​: my $cnt = ($arg =~ s/(.)/"$1"/e); f \<;> dbstate(main -5 C​:\Documents and Settings\Owner\Desktop\n11.pl​:21) v​:*\,&\,{\,x*\,x&\,x$\,$ g \<0> padsv[$arg​:-7\,-2] sRM h \</> subst(/"(.)"/ replstart->i) sKPS i \<0> enter s # 21​: my $cnt = ($arg =~ s/(.)/"$1"/e); j \<;> dbstate(main -6 C​:\Documents and Settings\Owner\Desktop\n11.pl​:21) v​:*\,&\,x*\,x&\,x$\,$ k \<#> gvsv[*1] s l \<@​> stringify[t7] sK/1 m \<@​> leave sK n \<|> substcont(other->h) sK/1 o \<0> padsv[$cnt​:-5\,-2] sRM*/LVINTRO p \<2> sassign vKS/2 # 22​: my $err = 0+$!; q \<;> dbstate(main -4 C​:\Documents and Settings\Owner\Desktop\n11.pl​:22) v​:*\,&\,{\,x*\,x&\,x$\,$ r \<$> const[IV 0] s s \<#> gvsv[*!] s t \<2> add[t10] sK/2 u \<0> padsv[$err​:-4\,-2] sRM*/LVINTRO v \<2> sassign vKS/2 # 23​: is ($cnt\, 1\, 'exactly one substitution performed'); w \<;> dbstate(main -3 C​:\Documents and Settings\Owner\Desktop\n11.pl​:23) v​:*\,&\,{\,x*\,x&\,x$\,$ x \<0> padrange[$cnt​:-5\,-2] s/1 y \<$> const[IV 1] sM z \<$> const[PV "exactly one substitution performed"] sM 10 \<#> gv[*is] s 11 \<1> entersub[t13] vKS/DBG\,TARG\,2 # 25​: local $TODO = "fails on $^O" if $^O eq 'MSWin32'; 12 \<;> dbstate(TODO​: main -2 C​:\Documents and Settings\Owner\Desktop\n11.pl​:25) v​:*\,&\,{\,x*\,x&\,x$\,$ 13 \<{> enterloop(next->1k last->1k redo->14) # 24​: TODO​: { 14 \<;> dbstate(main -3 C​:\Documents and Settings\Owner\Desktop\n11.pl​:24) v​:*\,&\,{\,x*\,x&\,x$\,$ 15 \<#> gvsv[*^O] s 16 \<$> const[PV "MSWin32"] s 17 \<2> seq sK/2 18 \<|> and(other->19) vK/1 19 \<$> const[PV "fails on "] s 1a \<#> gvsv[*^O] s 1b \<2> concat[t16] sK/2 1c \<#> gvsv[*TODO] s/LVINTRO 1d \<2> sassign vKS/2 # 26​: is ($err\, $arbitrary\, 'successful s///e does not clobber $!'); 1e \<;> dbstate(main -3 C​:\Documents and Settings\Owner\Desktop\n11.pl​:26) v​:*\,&\,{\,x*\,x&\,x$\,$ 1f \<0> padrange[$err​:-4\,-2] s/1 1g \<0> padsv[$arbitrary​:-8\,-2] sM 1h \<$> const[PV "successful s///e does not clobber $!"] sM 1i \<#> gv[*is] s 1j \<1> entersub[t21] KS/DBG\,TARG\,2 1k \<2> leaveloop K/2 1l \<1> leavesub[1 ref] K/REFC\,1 _________________________________________________________

Curcop says Test​::Builder line 871 which is _________________________________________________________ sub _unoverload {   my $self = shift;   my $type = shift;

  $self->_try(sub { require overload; }\, die_on_fail => 1); _________________________________________________________ I reran the procmon log with _________________________________________________________   local $! = my $arbitrary = 1;   my $arg = "a";   sleep 4;   my $cnt = ($arg =~ s/(.)/"$1"/e);   my $err = 0+$!;   sleep 4;   is ($cnt\, 1\, 'exactly one substitution performed');   TODO​: {   local $TODO = "fails on $^O" if $^O eq 'MSWin32';   is ($err\, $arbitrary\, 'successful s///e does not clobber $!');   } _________________________________________________________ no file IO for 8 seconds. A require() didn't happen from substitute operator on my machine so that was a false lead. Back to step 1/no ideas what causes $! to change.

-- bulk88 ~ bulk88 at hotmail.com

p5pRT commented 11 years ago

From @craigberry

On Fri\, Dec 28\, 2012 at 3​:26 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

The current tie between errno and $! is an implementation detail that might be changed

Yeah\, but it's a pretty fundamental implementation detail. It seems that what you really want is a variable that holds the most recent error from a Perl op rather than the most recent error from a syscall. That's not utterly crazy in theory\, but it is a pretty major feature request. The implementation cost and the run-time cost would likely be high. It reminds me a little bit of "safe" signals\, where we try to capture system information and present it as if it were information about a Perl op rather than information about various of the gory details that comprise the op. Getting safe signals right has been\, um\, interesting\, for various definitions of both "right" and "interesting" ;-).

It's not wrong to want newer and better ways of doing things\, but my guess would be that if something genuinely new and different and requiring major effort were in the cards it would be exception handling primitives rather than an errno replacement or even a slightly smarter errno.

If your only use of Perl is within a US-English localized unix\, then your view might be adequate.

While locale may change the text of the error string\, I really don't see what it has to do with when or whether errno gets set.

But it is a large world and there are ports around\, among them VMS and Win32\, and if I read correctly a port for Android is in progress. From my (admitely limited) understanding\, on VMS and Win32\, $! is only remotely related to the system errno.

On VMS\, the CRTL errno provides pretty good emulation of POSIX errno. You can sometimes get more detailed information from $^E\, but the semantics aren't any different. With native system calls\, there is no concept of "most recent error"; instead you get detailed error information from the return value\, or\, on low-level I/O completion\, the I/O status block\, or\, on higher-level I/O completion\, the appropriate fields in the file access block. None of which is particularly relevant here since when we make native calls\, errors are still reported to your Perl program using errno semantics.

I really think portability is a red herring here. The only substantive difference I can think of is that Win32 and VMS are more likely to implement syscall replacements and thus need to set errno themselves. There have been bugs in this area. If you find any more\, do report them.

The problem here of course is that require clobbers $! when successful\, when it should leave it well alone. I was planning to send it as a bug report cum TODO test but it does not seem to be worth the trouble if it gets also qualified as notabug.

Yes\, in general\, things should not touch errno when successful. But require is pretty special. If it's not obeying the general rule\, there may be a reason for it. Some analysis of why it is the way it is and what the implications are of changing it would have to be done before a change could be considered.

p5pRT commented 11 years ago

From @craigberry

On Sat\, Dec 29\, 2012 at 2​:49 PM\, Craig A. Berry \craig\.a\.berry@&#8203;gmail\.com wrote​:

On Fri\, Dec 28\, 2012 at 3​:26 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

The problem here of course is that require clobbers $! when successful\, when it should leave it well alone. I was planning to send it as a bug report cum TODO test but it does not seem to be worth the trouble if it gets also qualified as notabug.

Yes\, in general\, things should not touch errno when successful. But require is pretty special. If it's not obeying the general rule\, there may be a reason for it. Some analysis of why it is the way it is and what the implications are of changing it would have to be done before a change could be considered.

FWIW\, here is where pp_require started clearing errno​:

\<http​://perl5.git.perl.org/perl.git/commit/d8bfb8bddf933a815b590823bd52295534e6ded0?f=pp_ctl.c>

The only reason given is "suggested by Larry\," which is difficult to argue with and impossible to evaluate. There's no mystery about why the errno we've got isn't any good​: we've iterated through @​INC trying to open something\, and if we've succeeded on the 2nd or Nth try\, errno will have the failure code from try N - 1.

But why errno needs to be cleared rather than restored is a mystery to me. The following experimental patch causes us to save and restore errno on a successful require. E.g.\,

$ ./perl -Ilib -e '$!=99; require strict; print 0+$! . qq/\n/;' 99

I make no further claims about it except that I see no test failures with a quick build on OS X. Whether errno should be restored on a failed require is not addressed here\, and this patch should not be applied without further discussion; I'm just trying to help interested parties get connected with the code that implements what they're worried about.

$ git diff

Inline Patch ```diff diff --git a/pp_ctl.c b/pp_ctl.c index 199df1f..39a5a6a 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -3608,7 +3608,8 @@ PP(pp_require) SV *hook_sv = NULL; SV *encoding; OP *op; - int saved_errno; + int doopen_errno; + dSAVE_ERRNO; sv = POPs; if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) { @@ -3922,13 +3923,13 @@ PP(pp_require) } } } - saved_errno = errno; /* sv_2mortal can realloc things */ + doopen_errno = errno; /* sv_2mortal can realloc things */ sv_2mortal(namesv); if (!tryrsfp) { if (PL_op->op_type == OP_REQUIRE) { - if(saved_errno == EMFILE || saved_errno == EACCES) { + if(doopen_errno == EMFILE || doopen_errno == EACCES) { /* diag_listed_as: Can't locate %s */ - DIE(aTHX_ "Can't locate %s: %s", name, Strerror(saved_errno)); + DIE(aTHX_ "Can't locate %s: %s", name, ```

Strerror(doopen_errno));   } else {   if (namesv) { /* did we lookup @​INC? */   AV * const ar = GvAVn(PL_incgv); @​@​ -3972\,7 +3973\,7 @​@​ PP(pp_require)   RETPUSHUNDEF;   }   else - SETERRNO(0\, SS_NORMAL); + RESTORE_ERRNO;

  /* Assume success here to prevent recursive requirement. */   /* name is never assigned to again\, so len is still strlen(name) */ [end]

p5pRT commented 11 years ago

From @Leont

On Sun\, Dec 30\, 2012 at 1​:10 AM\, Craig A. Berry \craig\.a\.berry@&#8203;gmail\.com wrote​:

The only reason given is "suggested by Larry\," which is difficult to argue with and impossible to evaluate. There's no mystery about why the errno we've got isn't any good​: we've iterated through @​INC trying to open something\, and if we've succeeded on the 2nd or Nth try\, errno will have the failure code from try N - 1.

That said\, there are other things that can clobber errno\, most importantly the code inside the module can. How do we want to handle that?

Leon

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 29/12/2012 00​:01\, Leon Timmermans a écrit :

On Fri\, Dec 28\, 2012 at 10​:26 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

a contrived but simple example :

consider require\, and a program that might want to react smartly to a failure rather than simply exiting ; require dies on error. It does so with an occasionally less than useful message\, as the following demonstates :

[cm@​COS63 ~/badcarp]$ cat badrequire.pl use strict; use warnings; eval { require DoesNotExist; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; eval { require NotReadable; 1; } or do { my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E); print '$@​ : '\, $evalerr\, "\n"\, '$! : '\, $e+0\, " ($e)\n"\, '$^E​: '\, $se+0\, " ($se)\n"; }; [cm@​COS63 ~/badcarp]$ perl badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm in @​INC (@​INC contains​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$ ~/blead/perl/bin/perl5.17.7 badrequire.pl $@​ : Can't locate DoesNotExist.pm in @​INC (you may need to install the DoesNotExist module) (@​INC contains​: /home/cm/blead/perl/lib/site_perl/5.17.7/x86_64-linux /home/cm/blead/perl/lib/site_perl/5.17.7 /home/cm/blead/perl/lib/5.17.7/x86_64-linux /home/cm/blead/perl/lib/5.17.7 .) at badrequire.pl line 4.

$! : 2 (No such file or directory) $^E​: 2 (No such file or directory) $@​ : Can't locate NotReadable.pm​: Permission denied at badrequire.pl line 14.

$! : 13 (Permission denied) $^E​: 13 (Permission denied) [cm@​COS63 ~/badcarp]$

(as their names indicate\, DoesNotExist.pm does not exist\, and NotReadable.pm exists but is not readable by the perl process; the first run is the system perl v5.10.1\, the second is blead. Both on Linux COS63 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12​:19​:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux).

Even though the message is somewhat better with blead\, the easiest\, safest\, version-resilient\, in fact the only tractable way to react adequately to the error is to test the numerical value of $!.

I'm not really seeing your point here.

yes I'm afraid my rants muddle the message :-/ Let me try again.

0) I am very interested in programmatic error handling (meaning having the program react as intelligently as possible to errors\, by taking or initiating corrective measures adapted to the exact error raised : in the above example those measures would be different on ENOENT (2) or EACCES (13)).

1) I take require as an example of an op/sub that dies/croaks on error. 2) I show that the capturable string message can be less than useful for programmatic error handling. 3) I advocate that programmatic error handling is best performed (at least in certain situations) by dealing with the numerical values of $! and/or $^E 4) I conclude that carp and family (esp. croak and confess) should try their best not to clobber $! and $^E\, so that I can write code like

eval { some_sub_that_might_die_or_croak; 1 } or do {   my ($evalerr\, $e\, $se) = ($@​\, $!\, $^E);   if (ref $evalerr) {   ... # deal with exception object   } elsif (I_can_make_sense_of_this_error_string($evalerr) {   ... # deal with error string   } else { # deal with numerical errors   if ($e == ENOENT) {   ...   } elsif {$e == EACCES) {   ...   etc.   } };

This was really intended as a plea to Yves to consider favorably my wish that some functions try their best not to clobber $! and $^E.

The problem with the messages from die/croak is that even though they may use the string value of $!\, they usually lose the dual nature of $!\, which makes error handling much harder than necessary (is at all feasible). An other problem of course is that the message structure may vary from one version of Perl to the other (not to mention the execution locale).

My reference to a function that "might die/croak and need to report why through $! or $^E" was admitedly unclear. I hope the above clarifies the problem : to die or croak is useful to raise an error\, but unless you die with a rich exception object\, you will often need uncorrupted $! and $^E to perform any useful error handling.

Obviously this does not work in an optimal fashion\, but I don't think pimping up $! is the real solution for that. To the contrary\, it's making exceptions richer that is.

possibly. In the meantime there are subs and ops around that don't throw exceptions and most likely will not for any version of Perl5.

As a user of Perl I want $! and $^E to be useable. Maybe as a Perl core developer you are satisfied with tieing $! to errno and be done with it but IMHO this is a case of misplaced lazyness ;-) [take this with a pinch of salt : I don't understand enough of perl internals to have an informed view of the possible implementation\, and I have the utmost respect for the perl developers].

It's still not clear to me what other behavior you would want. It still sounds to me like you want a lollipop.

1) If a sub fails\, it is allowed to modify $! and $^E. That should be documented. 2) If it does not fail\, irrespective of any systems calls that it had to perform\, it should not clobber $! or $^E (meaning\, the values of $! and $^E on entry of the sub should be restored on exit). That should also be documented and tested.

This is possibly too costly as a general principle\, but useful at least for subs involved in error handling such as carp and family (and require\, if only because of the existence and pervasiveness of the 'delayed loading of carp and family' idiom).

Well\, it is maybe how the current implementation of $! works. Even if we do not change it I think it might be possible to obtain a consensus on the fact that it would be useful if some functions made an effort not to clobber $! and $^E if they don't have to. For instance I have patched a workable carp and family simply by localizing $! and $^E around the call to the subst mentioned in the original post. Also\, I believe that require should really behave as follows (pseudocode) : sub require {

my ($e\, $se) = ($!\, $^E); my $ret = ... current code ...

($!\, $^E) = ($e\, $se) return $ret; }

That's a rather crude hack\, and I doubt that's the best solution in most cases.

It has served me well so far.

I have not tested this on require of course. However because of the possible lossage with delayed loading of Carp\, I have long since made it a habit to require Carp as early as possible in my main scripts as a safety measure.

in practice\, since having croak and family respect $! and $^E is much more practical and easier (I routinely patch them for my own production work)\, I prefer the latter ;-)

I think that what you really want here is that longmess and shortmess "respect" $! and $^E. Because AFAICT they don't really have any good reason to want to modify them. carp/croak/cluck/confess however do (or better said\, the die/warn in them do).

that is close to my first draft wording for this bug report. Please recall that I explicitely mentioned in the report the problem with Carp​::format_args. But then I thought that I saw no good reason for s///e to clobber $! on success\, all the more so that it does so only on windows (AFAIK) and not on unices\, and I felt it better to point to the (IMO) true cause of the problem rather that on a symptom.

I might live with a cure for the symptom though...

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 30/12/2012 01​:10\, Craig A. Berry a écrit :

On Sat\, Dec 29\, 2012 at 2​:49 PM\, Craig A. Berry \craig\.a\.berry@&#8203;gmail\.com wrote​:

On Fri\, Dec 28\, 2012 at 3​:26 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

The problem here of course is that require clobbers $! when successful\, when it should leave it well alone. I was planning to send it as a bug report cum TODO test but it does not seem to be worth the trouble if it gets also qualified as notabug.

Yes\, in general\, things should not touch errno when successful. But require is pretty special. If it's not obeying the general rule\, there may be a reason for it. Some analysis of why it is the way it is and what the implications are of changing it would have to be done before a change could be considered.

FWIW\, here is where pp_require started clearing errno​:

\<http​://perl5.git.perl.org/perl.git/commit/d8bfb8bddf933a815b590823bd52295534e6ded0?f=pp_ctl.c>

The only reason given is "suggested by Larry\," which is difficult to argue with and impossible to evaluate. There's no mystery about why the errno we've got isn't any good​: we've iterated through @​INC trying to open something\, and if we've succeeded on the 2nd or Nth try\, errno will have the failure code from try N - 1.

But why errno needs to be cleared rather than restored is a mystery to me. The following experimental patch causes us to save and restore errno on a successful require. E.g.\,

$ ./perl -Ilib -e '$!=99; require strict; print 0+$! . qq/\n/;' 99

I make no further claims about it except that I see no test failures with a quick build on OS X. Whether errno should be restored on a failed require is not addressed here\, and this patch should not be applied without further discussion; I'm just trying to help interested parties get connected with the code that implements what they're worried about.

Thank you! Now\, as is well known\, the reward for a job well done is more work :-) If you could also make it so that it does not clobber $^E either\, I'd be in heaven...

Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl clobberingrequire.pl 1..2 not ok 1 - require does not obviously clobber $! # Failed test 'require does not obviously clobber $!' # at clobberingrequire.pl line 7. # got​: '0' # expected​: '1' not ok 2 - require does not obviously clobber $^E # Failed test 'require does not obviously clobber $^E' # at clobberingrequire.pl line 8. # got​: '203' # expected​: '1' # BTW\, 203 is 'Le système n’a pas trouvé l’option d’environnement spécifiée' # Looks like you failed 2 tests of 2. Taisha​:\~/perl/patches/badcarp $ PATH=/cygdrive/d/perl/site/bin​:/cygdrive/d/perl/bin​:/cygdrive/d/c/bin perl -V Summary of my perl5 (revision 5 version 17 subversion 7) configuration​:   Derived from​:   Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags =' -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields'\,   optimize='-s -O2'\,   cppflags='-DWIN32'   ccversion=''\, gccversion='4.6.3'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='long long'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='g++'\, ldflags ='-s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"'   libpth=C​:\MinGW\lib   libs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   perllibs=-lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32   libc=\, so=dll\, useshrplib=true\, libperl=libperl517.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-mdll -s -L"d​:\perl\lib\CORE" -L"C​:\MinGW\lib"'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE   PERL_PRESERVE_IVUV USE_64_BIT_INT USE_ITHREADS   USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE   USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO   USE_PERL_ATOF   Locally applied patches​:   uncommitted-changes   Built under MSWin32   Compiled at Dec 17 2012 13​:09​:34   @​INC​:   D​:/perl/site/lib   D​:/perl/lib   . Taisha​:\~/perl/patches/badcarp $

===================================================================

C​:\Users\Administrator>type clobberingrequire.pl use strict; use warnings; use Test​::More tests => 2; {   local ($!\, $^E) = my ($e\, $se) = (1\, 1);   require Carp;   is (0+$! \, $e \, q{require does not obviously clobber $!});   is (0+$^E\, $se\, q{require does not obviously clobber $^E})   or diag ("BTW\, " . (0+$^E) . " is '$^E'"); }

C​:\Users\Administrator>C​:\Perl64\bin\perl -w clobberingrequire.pl 1..2 not ok 1 - require does not obviously clobber $! # Failed test 'require does not obviously clobber $!' # at clobberingrequire.pl line 7. # got​: '0' # expected​: '1' not ok 2 - require does not obviously clobber $^E # Failed test 'require does not obviously clobber $^E' # at clobberingrequire.pl line 8. # got​: '203' # expected​: '1' # BTW\, 203 is 'The system could not find the environment option that was entered' # Looks like you failed 2 tests of 2.

C​:\Users\Administrator>C​:\Perl64\bin\perl -V Summary of my perl5 (revision 5 version 16 subversion 1) configuration​:

  Platform​:   osname=MSWin32\, osvers=5.2\, archname=MSWin32-x64-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -Ox -GL -fp​:precise -DWIN32 -D_CONSOLE -DNO_STRICT -DWIN64 -DCONSERVATIVE -DPERL_TEXTMODE_SCRIPTS -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -D USE_PERLIO'\,   optimize='-MD -Zi -DNDEBUG -Ox -GL -fp​:precise'\,   cppflags='-DWIN32'   ccversion='14.00.40310.41'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=8   ivtype='__int64'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='__int64'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'   libpth=\lib   libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib comctl32.lib bufferoverflowU.lib msvcrt.lib   perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32. lib comctl32.lib bufferoverflowU.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=true\, libperl=perl516.lib   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -ltcg -libpath​:"C​:\Perl64\lib\CORE" -machine​:AMD64'

Characteristics of this binary (from libperl)​:   Compile-time options​: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY   PERLIO_LAYERS PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS   PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE   USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF   USE_SITECUSTOMIZE   Locally applied patches​:   ActivePerl Build 1601 [296175]   Built under MSWin32   Compiled at Aug 30 2012 18​:41​:50   @​INC​:   C​:/Perl64/site/lib   C​:/Perl64/lib   .

C​:\Users\Administrator>

p5pRT commented 11 years ago

From @craigberry

On Sat\, Dec 29\, 2012 at 7​:21 PM\, Leon Timmermans \fawaka@&#8203;gmail\.com wrote​:

On Sun\, Dec 30\, 2012 at 1​:10 AM\, Craig A. Berry \craig\.a\.berry@&#8203;gmail\.com wrote​:

The only reason given is "suggested by Larry\," which is difficult to argue with and impossible to evaluate. There's no mystery about why the errno we've got isn't any good​: we've iterated through @​INC trying to open something\, and if we've succeeded on the 2nd or Nth try\, errno will have the failure code from try N - 1.

That said\, there are other things that can clobber errno\, most importantly the code inside the module can. How do we want to handle that?

Good point. If I'm understanding all the macros in pp_require (but I haven't taken the time to expand and study them)\, the point at which we were clearing errno (but after my tentative patch restore it) is after successfully opening the required file but before reading it in\, parsing it\, and compiling it. It kinda makes sense that rooting through @​INC trying to find the file is not something we'd report back on\, but trouble actually loading the module once we've found it is something the caller needs to know about. Restoring rather than clearing doesn't change that.

p5pRT commented 11 years ago

From @craigberry

On Sat\, Dec 29\, 2012 at 8​:22 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Thank you! Now\, as is well known\, the reward for a job well done is more work :-) If you could also make it so that it does not clobber $^E either\, I'd be in heaven...

You're welcome\, but I'm not going to do *all* your homework for you. Be sure to read the Perl docs on $^E and the Microsoft docs on GetLastError()\, the latter of which explicitly state that successful calls may clear the most recent error. And consider firing up your Visual Studio debugger and setting breakpoints for Perl_pp_require in pp_ctl.c and Perl_magic_get in mg.c (for $^E). Step through the code and figure out what it's doing now and why before proposing to change it.

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 30/12/2012 04​:53\, Craig A. Berry a écrit :

On Sat\, Dec 29\, 2012 at 8​:22 PM\, Christian Millour \cm\.perl@&#8203;abtela\.com wrote​:

Thank you! Now\, as is well known\, the reward for a job well done is more work :-) If you could also make it so that it does not clobber $^E either\, I'd be in heaven...

You're welcome\, but I'm not going to do *all* your homework for you.

Ouch. Please don't shoot the messenger\, although I guess I deserved that\, if only because of my clumsy wording. Problem is\, I have at this point very little true understanding of the perl internals. I *have* tried to run perl under debugger in Win32 with precious little success so far...

Be sure to read the Perl docs on $^E and the Microsoft docs on GetLastError()\, the latter of which explicitly state that successful calls may clear the most recent error. And consider firing up your Visual Studio debugger and setting breakpoints for Perl_pp_require in pp_ctl.c and Perl_magic_get in mg.c (for $^E). Step through the code and figure out what it's doing now and why before proposing to change it.

Thanks for the hints. I'll try again :-)

p5pRT commented 11 years ago

From @jandubois

On Sat\, Dec 29\, 2012 at 5​:39 PM\, Christian Millour \cm\.perl@&#8203;abtela\.comwrote​:

0) I am very interested in programmatic error handling (meaning having the program react as intelligently as possible to errors\, by taking or initiating corrective measures adapted to the exact error raised : in the above example those measures would be different on ENOENT (2) or EACCES (13)).

1) I take require as an example of an op/sub that dies/croaks on error. 2) I show that the capturable string message can be less than useful for programmatic error handling. 3) I advocate that programmatic error handling is best performed (at least in certain situations) by dealing with the numerical values of $! and/or $^E 4) I conclude that carp and family (esp. croak and confess) should try their best not to clobber $! and $^E\, so that I can write code like

Even then you still have the problem that any DESTROY method run while unwinding the stack back to the eval() handler may modify $! and $^E again. So these values would also need to be handled similar to $@​.

Cheers\, -Jan

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 31/12/2012 18​:27\, Jan Dubois a écrit :

On Sat\, Dec 29\, 2012 at 5​:39 PM\, Christian Millour \<cm.perl@​abtela.com \mailto&#8203;:cm\.perl@&#8203;abtela\.com> wrote​:

0\) I am very interested in programmatic error handling \(meaning
having the program react as intelligently as possible to errors\, by
taking or initiating corrective measures adapted to the exact error
raised : in the above example those measures would be different on
ENOENT \(2\) or EACCES \(13\)\)\.

1\) I take require as an example of an op/sub that dies/croaks on error\.
2\) I show that the capturable string message can be less than useful
for programmatic error handling\.
3\) I advocate that programmatic error handling is best performed \(at
least in certain situations\) by dealing with the numerical values of
$\! and/or $^E
4\) I conclude that carp and family \(esp\. croak and confess\) should
try their best not to clobber $\! and $^E\, so that I can write code like

Even then you still have the problem that any DESTROY method run while unwinding the stack back to the eval() handler may modify $! and $^E again.

that is one of the reasons I believe that perl ops and primitives should not ever clobber $! and $^E on success. It would mean that successful automatic resource liberation (such as closing a lexical filehandle) in DESTROY methods would not modify $! and $^E.

Non ignorable errors raised during stack unwinding are a mess anyway and call for more sophisticated handling strategies than the simple one previously outlined.

If an op really has a good reason to set or reset $! on success then this exceptional behavior should be documented so that we may work around it when we need to. For instance if require really has a good reason to reset $! on success (which is possible)\, and a good reason to pollute $^E on success (which IMO is unlikely)\, the 'delayed loading of Carp' idiom could be rewritten from the current   sub carp {   require Carp;   goto &Carp​::carp;   } to something like   sub carp {   { local ($!\, $^E); require Carp }   goto &Carp​::carp;   } in order to avoid the previously described lurking trap with carp $!. A similar strategy might be used when needed in DESTROY methods.

    So these values would also need to be handled similar to $@&#8203;\.

Could you please expand on this or give me a pointer to what you mean ?

Best regards\, and season greetings to all

-Christian

p5pRT commented 11 years ago

From @jandubois

On Wed\, Jan 2\, 2013 at 9​:07 AM\, Christian Millour \cm\.perl@&#8203;abtela\.comwrote​:

    So these values would also need to be handled similar to $@&#8203;\.

Could you please expand on this or give me a pointer to what you mean ?

http​://perl5.git.perl.org/perl.git/blob/HEAD​:/pod/perl5140delta.pod#l350

Cheers\, -Jan

p5pRT commented 11 years ago

From cm.perl@abtela.com

Le 28/12/2012 19​:51\, bulk88 via RT a écrit :

                 it doesn't fail on unix anyway \(according to other

posts in this thread)\, and nobody has identified what Win32 C C-lib call caused C errno to be changed.

found it : atoi. See why below.

-something to do with msvcrt.dll on NT 6\, ActivePerl and Strawberry Perl use msvcrt.dll on 32 and 64 Windows. Most personal Visual C builds use a msvcr##.dll.

Heartfelt thanks for your time and efforts on this. You are right on the mark. With recent versions of msvcrt.dll\, atoi resets errno on success (which it doesn't do on linux\, and older msvcrt.dll on Win32). Consider the following C program

G​:\>type test_atoi.c #include \<stdio.h> #include \<stdlib.h> #include \<errno.h> int main() {   int x;   errno = 99;   x = atoi("123");   printf("%d\n"\, errno); } G​:\>

On linux I get

[cm@​COS63 ~/badcarp]$ gcc tatoi.c [cm@​COS63 ~/badcarp]$ ./a.out 99 [cm@​COS63 ~/badcarp]$

On my machine (a 64bit Win7 R1) compiling with mingw 32 and 64 (actually\, the versions provided in the c directory of strawberry perl portable 5.16.2.1\, versions 32 and 64 bits resp.)\, to produce t32.exe and t64.exe (details in attached compile.txt)\, I get

G​:\testatoi>.\t32.exe 0 G​:\testatoi>.\t64.exe 0 G​:\testatoi>

I have run these two programs on a variety of WIN32 machines. The results are summarized below (the two fist colums are the output of t32.exe and t64.exe -- when available\, i.e. when the architecture is indeed 64 bits)​:

+----+----+----------------+-----+----------+--------------------+-----+ | 32 | 64 | msvcrt.dll | Arc | Version | Caption Alias | SP | +----+----+----------------+-----+----------+--------------------+-----+ | 99 | -- | 6.10.9844.0 | 32b | 5.0.2195 | 2000 Pro | SP4 | | 99 | -- | 7.0.2600.5512 | 32b | 5.1.2600 | XP Pro | SP3 | | 99 | -- | 7.0.3790.3959 | 32b | 5.2.3790 | S. 2003 Std Ed | SP2 | | 99 | 99 | 7.0.3790.3959 | 64b | 5.2.3790 | S. 2003 Std x64 Ed | SP2 | | 0 | 0 | 7.0.6002.18551 | 64b | 6.0.6002 | S. 2008 Std | SP2 | | 0 | -- | 7.0.7601.17744 | 32b | 6.1.7601 | 7 Pro | SP1 | | 0 | 0 | 7.0.7601.17744 | 64b | 6.1.7601 | S. 2008 R2 Std | SP1 | | 0 | 0 | 7.0.7601.17744 | 64b | 6.1.7601 | 7 Int | SP1 | | 0 | 0 | 7.0.9200.16384 | 64b | 6.2.9200 | 8 Pro | | +----+----+----------------+-----+----------+--------------------+-----+

This would explain your difficulties in reproducing the problem.

Back to Perl\, the behavior described in the original report has nothing to do with the e flag in a subst as I initially suspected\, but with accessing the numbered match vars ($1\, $2\, etc). See Win32_gdb.txt (attached) for a sample gdb session with a 'debug blead' which can't make test but is sufficient for this purpose (g​:\SPPC is a copy of the c directory of strawberry perl portable 5.16.2.1 64bits\, so it is really the migw64 compiler).

Any use of $\ or (getting $&) will reset errno (and thus $!) because the \ and ('&' in get) are parsed with atoi in mg.c​:Perl_magic_get/set. A cursory analysis of the use of atoi in core reveals some easily testable potential problems in recomp.c​:S_reg\, as well as potential edge-case problems (very difficult to test) with malloc.c​:realloc and malloc.c​:free

________________________________________________________________ Taisha​:/cygdrive/g/perls/blead/git/win32 $ cat ../../../myt/atoi_clobbering_errno.t use strict; use warnings; use Test​::More tests => 7;

# from use of atoi in mg.c {   local $!;   my $x = q{x};   $x =~ m/(?\.)/; # set match vars

  $! = 99;   my $estr = "$!";   is "$1$!"\, "$x$estr"\, 'can use $1 and $! in same expression';

  $! = 99;   is "$&$!"\, "$x$estr"\, 'can use $& and $! in same expression';

  $! = 99;   my $a = $&;   is 0+$!\, 99\, 'getting $& does not clobber $!';

  $! = 99;   $a = $1;   is 0+$!\, 99\, 'getting $1 does not clobber $!';

  $! = 99;   eval { $1 = 0 }; # croaks\, but *after* atoi is called   is 0+$!\, 99\, 'attempting to set $1 does not clobber $!'; }

# from use of atoi in regcomp.c {   local $! = 99;   my $res = q{(.)\1};   my $re = qr{$res};   is 0+$!\, 99\, 'dynamic qr// with backrefs does not clobber $!';

  $! = 99;   $res = q{.{0\,1}};   $re = qr{$res};   is 0+$!\, 99\, 'dynamic qr// with quantifiers does not clobber $!'; }

________________________________________________________________ Taisha​:/cygdrive/g/perls/blead/git/win32 $ perl -v | head -2

This is perl\, v5.10.1 (*) built for i686-cygwin-thread-multi-64int Taisha​:/cygdrive/g/perls/blead/git/win32 $ perl ../../../myt/atoi_clobbering_errno.t 1..7 ok 1 - can use $1 and $! in same expression ok 2 - can use $& and $! in same expression ok 3 - getting $& does not clobber $! ok 4 - getting $1 does not clobber $! ok 5 - attempting to set $1 does not clobber $! ok 6 - dynamic qr// with backrefs does not clobber $! ok 7 - dynamic qr// with quantifiers does not clobber $! ________________________________________________________________ Taisha​:/cygdrive/g/perls/blead/git/win32 $ ../perl -v | head -2

This is perl 5\, version 17\, subversion 8 (v5.17.8) built for MSWin32-x64-multi-thread Taisha​:/cygdrive/g/perls/blead/git/win32 $ ../perl ../../../myt/atoi_clobbering_errno.t 1..7 not ok 1 - can use $1 and $! in same expression # Failed test 'can use $1 and $! in same expression' # at ../../../myt/atoi_clobbering_errno.t line 13. # got​: 'x' # expected​: 'xUnknown Error' not ok 2 - can use $& and $! in same expression # Failed test 'can use $& and $! in same expression' # at ../../../myt/atoi_clobbering_errno.t line 16. # got​: 'x' # expected​: 'xUnknown Error' not ok 3 - getting $& does not clobber $! # Failed test 'getting $& does not clobber $!' # at ../../../myt/atoi_clobbering_errno.t line 20. # got​: '0' # expected​: '99' not ok 4 - getting $1 does not clobber $! # Failed test 'getting $1 does not clobber $!' # at ../../../myt/atoi_clobbering_errno.t line 24. # got​: '0' # expected​: '99' not ok 5 - attempting to set $1 does not clobber $! # Failed test 'attempting to set $1 does not clobber $!' # at ../../../myt/atoi_clobbering_errno.t line 28. # got​: '0' # expected​: '99' not ok 6 - dynamic qr// with backrefs does not clobber $! # Failed test 'dynamic qr// with backrefs does not clobber $!' # at ../../../myt/atoi_clobbering_errno.t line 36. # got​: '0' # expected​: '99' not ok 7 - dynamic qr// with quantifiers does not clobber $! # Failed test 'dynamic qr// with quantifiers does not clobber $!' # at ../../../myt/atoi_clobbering_errno.t line 41. # got​: '0' # expected​: '99' # Looks like you failed 7 tests of 7. Taisha​:/cygdrive/g/perls/blead/git/win32 $ ________________________________________________________________

This ill-behavior of atoi is likely here to stay\, given that all recent versions (6+) of Win32 are affected. I would not be surprised if it also crept into the run time libraries (msvcr##.dll) of the future version of the MS compiler.

So\, how to fix this ? The obvious substitute\, strtol\, is out because it exhibits the same resetting-errno-on-success behavior. And in any case it would be wasteful : the use of atoi in generic (non-OS-specific) core code falls into two categories 1) parsing a positive index : $1\, $2\, ... ; \1 or \g{1} in regexp ; a file descriptor 2) parsing the value of an environment variable It is always assumed that the call succeeds so any work performed by the function to detect and report overflow is wasted. There are never leading spaces in the parsed strings. The indices are always positive (although the environment variables might not be\, and 0123 and -123 yield true for env vars... not sure it is usefult but strict backward compatability would require ability to parse siged numbers).

A possible fix would be to add a Perl_my_atoi in numeric.c\, on the model of Perl_my_atof\, and use Perl_atoi instead of atoi in (at least) mg.c and reg_comp.c.

perl.h​: #if defined( WIN32 ) && !defined(__CYGWIN__) #define Perl_atoi Perl_my_atoi #else #define Perl_atoi atoi #endif

numeric.c​: int Perl_my_atoi(char const * s) {   int i\, n\, sign;   for (i = 0; isspace(s[i]); i++);   sign = (s[i] == '-') ? -1 : 1;   if (s[i] == '+' || s[i] == '-')   i++;   for (n = 0; isdigit(s[i]); i++)   n = 10 * n + (s[i] - '0');   return sign * n; }

I am willing to produce a patch and test files if this solution is deemed agreeable. I believe this could be (marginally) beneficial to all versions\, and possibly of some interest to some XS code that does not need to check overflow. FWIW\, the straight K&R version above is about 10 times faster that atoi on my box with gcc -03\, and could certainly be optimised further. On the other hand\, for added security this function might detect overflow but report it via warn/croak. What do you think ?

Thanks for your time\, and best regards\,

Christian.