Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

Closed
p5pRT opened this issue Dec 17, 2012 · 61 comments
Closed

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

p5pRT opened this issue Dec 17, 2012 · 61 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 17, 2012

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

Searchable as RT116118$

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2012

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
Copy link
Author

p5pRT commented Dec 17, 2012

From cm.perl@abtela.com

0001-Add-test-TODO-on-MSWin32-successful-s-e-does-not-clo.patch
From 9765f5da1323607e17cb368c3d7e4cb75c31cbd0 Mon Sep 17 00:00:00 2001
From: Christian Millour <cm.perl@abtela.com>
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
Copy link
Author

p5pRT commented Dec 17, 2012

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
Copy link
Author

p5pRT commented Dec 17, 2012

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

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2012

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
Copy link
Author

p5pRT commented Dec 17, 2012

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
Copy link
Author

p5pRT commented Dec 17, 2012

From @demerphq

On 18 December 2012 00​:20, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 17, 2012

From @demerphq

On 18 December 2012 00​:27, Jesse Luehrs <doy@​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
Copy link
Author

p5pRT commented Dec 17, 2012

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 93a641a v5.17.6-186-g93a641a)
configur
tion​:
  Snapshot of​: 93a641a
  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
Copy link
Author

p5pRT commented Dec 17, 2012

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2012

From @Leont

On Tue, Dec 18, 2012 at 12​:27 AM, Jesse Luehrs <doy@​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
Copy link
Author

p5pRT commented Dec 18, 2012

From @doy

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

On 18 December 2012 00​:27, Jesse Luehrs <doy@​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
Copy link
Author

p5pRT commented Dec 18, 2012

From @bulk88

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

On Tue, Dec 18, 2012 at 12​:27 AM, Jesse Luehrs <doy@​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
Copy link
Author

p5pRT commented Dec 18, 2012

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@​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
Copy link
Author

p5pRT commented Dec 18, 2012

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
Copy link
Author

p5pRT commented Dec 18, 2012

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@​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
Copy link
Author

p5pRT commented Dec 18, 2012

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 93a641a v5.17.6-186-g93a641a)
configura
tion​:
  Snapshot of​: 93a641a
  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
Copy link
Author

p5pRT commented Dec 18, 2012

From @ikegami

On Mon, Dec 17, 2012 at 6​:20 PM, Christian Millour <cm.perl@​abtela.com>wrote​:

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<read>, C<print> and C<open>!

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2012

From @ikegami

On Mon, Dec 17, 2012 at 7​:03 PM, Jesse Luehrs <doy@​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
Copy link
Author

p5pRT commented Dec 18, 2012

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 93a641a v5.17.6-186-g93a641a)
configura
tion​:
  Snapshot of​: 93a641a
  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
Copy link
Author

p5pRT commented Dec 18, 2012

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
  1bac5ec 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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

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\ADMINI1\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
Copy link
Author

p5pRT commented Dec 28, 2012

From cm.perl@abtela.com

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

On 18 December 2012 00​:20, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

From @demerphq

On 28 December 2012 17​:21, Christian Millour <cm.perl@​abtela.com> wrote​:

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

On 18 December 2012 00​:20, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

From @Leont

On Fri, Dec 28, 2012 at 10​:26 PM, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 28, 2012

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
Copy link
Author

p5pRT commented Dec 28, 2012

From @bulk88

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

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2012

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
Copy link
Author

p5pRT commented Dec 29, 2012

From @craigberry

On Fri, Dec 28, 2012 at 3​:26 PM, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 30, 2012

From @craigberry

On Sat, Dec 29, 2012 at 2​:49 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

On Fri, Dec 28, 2012 at 3​:26 PM, Christian Millour <cm.perl@​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 --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
Copy link
Author

p5pRT commented Dec 30, 2012

From @Leont

On Sun, Dec 30, 2012 at 1​:10 AM, Craig A. Berry <craig.a.berry@​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
Copy link
Author

p5pRT commented Dec 30, 2012

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@​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
Copy link
Author

p5pRT commented Dec 30, 2012

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@​gmail.com> wrote​:

On Fri, Dec 28, 2012 at 3​:26 PM, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 30, 2012

From @craigberry

On Sat, Dec 29, 2012 at 7​:21 PM, Leon Timmermans <fawaka@​gmail.com> wrote​:

On Sun, Dec 30, 2012 at 1​:10 AM, Craig A. Berry <craig.a.berry@​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
Copy link
Author

p5pRT commented Dec 30, 2012

From @craigberry

On Sat, Dec 29, 2012 at 8​:22 PM, Christian Millour <cm.perl@​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
Copy link
Author

p5pRT commented Dec 30, 2012

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@​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
Copy link
Author

p5pRT commented Dec 31, 2012

From @jandubois

On Sat, Dec 29, 2012 at 5​:39 PM, Christian Millour <cm.perl@​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.
So these values would also need to be handled similar to $@​.

Cheers,
-Jan

@p5pRT
Copy link
Author

p5pRT commented Jan 2, 2013

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​:cm.perl@​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
Copy link
Author

p5pRT commented Jan 2, 2013

From @jandubois

On Wed, Jan 2, 2013 at 9​:07 AM, Christian Millour <cm.perl@​abtela.com>wrote​:

    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
Copy link
Author

p5pRT commented Jan 11, 2013

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 $&lt;digits&gt; or (getting $&amp;) will reset errno (and thus $!)
because the <digits> 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/(?<A>.)/; # set match vars

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

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

  $! = 99;
  my $a = $&amp;;
  is 0+$!, 99, 'getting $&amp; 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 $&amp; and $! in same expression
ok 3 - getting $&amp; 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 $&amp; and $! in same expression
# Failed test 'can use $&amp; and $! in same expression'
# at ../../../myt/atoi_clobbering_errno.t line 16.
# got​: 'x'
# expected​: 'xUnknown Error'
not ok 3 - getting $&amp; does not clobber $!
# Failed test 'getting $&amp; 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.

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2013

From cm.perl@abtela.com

Microsoft Windows [version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Tous droits réservés.

C​:\Users\cm>g​:

G​:\>cd testatoi

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

G​:\testatoi>set PATH=c​:\strawberry-perl-5.16.2.1-32bit-portable\c\bin

G​:\testatoi>gcc -v tatoi.c -o t32
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../libexec/gcc/i686-w64-mingw32/4.6.3/lto-wrapper.exe
Target​: i686-w64-mingw32
Configured with​: ../../../src/gcc-4.6.3/configure --build=i686-w64-mingw32 --target=i686-w64-mingw32 --enable-languages=c,c++,fortran --enable-libgomp
--enable-lto --enable-bootstrap --enable-checking=release --enable-version-specific-runtime-libs --disable-multilib --disable-nls --disable-win32-reg
istry --disable-werror --with-pkgversion='gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]' --with-sysroot=/gccbuild/prefix/mingw32
--with-gmp=/gccbuild/prefix/mingw32 --with-mpfr=/gccbuild/prefix/mingw32 --with-mpc=/gccbuild/prefix/mingw32 --with-ppl=/gccbuild/prefix/mingw32 --wi
th-cloog=/gccbuild/prefix/mingw32 --enable-cloog-backend=isl --with-bugurl=http​://mingwfp.znix.com --with-gnu-ld --prefix=/gccbuild/prefix/mingw32 --w
ith-local-prefix=/gccbuild/prefix/mingw32 --with-libiconv-prefix=/gccbuild/prefix/mingw32
Thread model​: win32
gcc version 4.6.3 (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net])
COLLECT_GCC_OPTIONS='-v' '-o' 't32.exe' '-mtune=generic' '-march=pentiumpro'
c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../libexec/gcc/i686-w64-mingw32/4.6.3/cc1.exe -quiet -v -iprefix c​:\strawberry-perl-5.16.2.1-32bit-p
ortable\c\bin\../lib/gcc/i686-w64-mingw32/4.6.3/ tatoi.c -quiet -dumpbase tatoi.c -mtune=generic -march=pentiumpro -auxbase tatoi -version -o C​:\Users
\cm\AppData\Local\Temp\ccSfkQ5T.s
GNU C (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) version 4.6.3 (i686-w64-mingw32)
  compiled by GNU C version 4.6.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics​: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-32bit-portable/c/lib/gcc/../../lib/gcc/i686-w64-mingw32/4.6.3/include"
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-32bit-portable/c/lib/gcc/../../lib/gcc/i686-w64-mingw32/4.6.3/include-fixed"
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-32bit-portable/c/lib/gcc/../../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/i
nclude"
#include "..." search starts here​:
#include <...> search starts here​:
c​:\strawberry-perl-5.16.2.1-32bit-portable\c\bin\../lib/gcc/i686-w64-mingw32/4.6.3/include
c​:\strawberry-perl-5.16.2.1-32bit-portable\c\bin\../lib/gcc/i686-w64-mingw32/4.6.3/include-fixed
c​:\strawberry-perl-5.16.2.1-32bit-portable\c\bin\../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/include
c​:/strawberry-perl-5.16.2.1-32bit-portable/c/lib/gcc/../../lib/gcc/i686-w64-mingw32/4.6.3/../../../../include
End of search list.
GNU C (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) version 4.6.3 (i686-w64-mingw32)
  compiled by GNU C version 4.6.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics​: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum​: 2aacb8624ae758373a5088eddce367da
COLLECT_GCC_OPTIONS='-v' '-o' 't32.exe' '-mtune=generic' '-march=pentiumpro'
c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/as.exe -o C​:\Users\cm\AppData\Loc
al\Temp\ccGcASLF.o C​:\Users\cm\AppData\Local\Temp\ccSfkQ5T.s
COMPILER_PATH=c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../libexec/gcc/i686-w64-mingw32/4.6.3/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin
/../libexec/gcc/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/
LIBRARY_PATH=c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../l
ib/gcc/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/lib/../lib/;c​:/strawberry-perl
-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../lib/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64
-mingw32/4.6.3/../../../../i686-w64-mingw32/lib/;c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../
COLLECT_GCC_OPTIONS='-v' '-o' 't32.exe' '-mtune=generic' '-march=pentiumpro'
c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../libexec/gcc/i686-w64-mingw32/4.6.3/collect2.exe --sysroot=c​:/gccbuild/prefix/mingw32 -m i386pe -B
dynamic -o t32.exe c​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/lib/../lib/crt2.o c
:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/crtbegin.o -Lc​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib
/gcc/i686-w64-mingw32/4.6.3 -Lc​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc -Lc​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gc
c/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/lib/../lib -Lc​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/
../../../../lib -Lc​:/strawberry-perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/lib -Lc​:/strawberry-
perl-5.16.2.1-32bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../.. C​:\Users\cm\AppData\Local\Temp\ccGcASLF.o -lmingw32 -lgcc_eh -lgcc -lmol
dname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt c​:/strawberry-perl-5.16.2.1-3
2bit-portable/c/bin/../lib/gcc/i686-w64-mingw32/4.6.3/crtend.o

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

G​:\testatoi>set PATH=c​:\strawberry-perl-5.16.2.1-64bit-portable\c\bin

G​:\testatoi>gcc -v tatoi.c -o t64
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../libexec/gcc/x86_64-w64-mingw32/4.6.3/lto-wrapper.exe
Target​: x86_64-w64-mingw32
Configured with​: ../../../src/gcc-4.6.3/configure --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --enable-languages=c,c++,fortran --enable-lib
gomp --enable-lto --enable-bootstrap --enable-checking=release --enable-version-specific-runtime-libs --disable-multilib --disable-nls --disable-win32
-registry --disable-werror --with-pkgversion='gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]' --with-sysroot=/gccbuild/prefix/min
gw64 --with-gmp=/gccbuild/prefix/mingw64 --with-mpfr=/gccbuild/prefix/mingw64 --with-mpc=/gccbuild/prefix/mingw64 --with-ppl=/gccbuild/prefix/mingw64
--with-cloog=/gccbuild/prefix/mingw64 --enable-cloog-backend=isl --with-bugurl=http​://mingwfp.znix.com --with-gnu-ld --prefix=/gccbuild/prefix/mingw64
--with-local-prefix=/gccbuild/prefix/mingw64 --with-libiconv-prefix=/gccbuild/prefix/mingw64
Thread model​: win32
gcc version 4.6.3 (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net])
COLLECT_GCC_OPTIONS='-v' '-o' 't64.exe' '-mtune=generic' '-march=x86-64'
c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../libexec/gcc/x86_64-w64-mingw32/4.6.3/cc1.exe -quiet -v -iprefix c​:\strawberry-perl-5.16.2.1-64bit
-portable\c\bin\../lib/gcc/x86_64-w64-mingw32/4.6.3/ tatoi.c -quiet -dumpbase tatoi.c -mtune=generic -march=x86-64 -auxbase tatoi -version -o C​:\Users
\cm\AppData\Local\Temp\ccj2g4q2.s
GNU C (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) version 4.6.3 (x86_64-w64-mingw32)
  compiled by GNU C version 4.6.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics​: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-64bit-portable/c/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/4.6.3/include"
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-64bit-portable/c/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/4.6.3/include-fixed"
ignoring duplicate directory "c​:/strawberry-perl-5.16.2.1-64bit-portable/c/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw
32/include"
#include "..." search starts here​:
#include <...> search starts here​:
c​:\strawberry-perl-5.16.2.1-64bit-portable\c\bin\../lib/gcc/x86_64-w64-mingw32/4.6.3/include
c​:\strawberry-perl-5.16.2.1-64bit-portable\c\bin\../lib/gcc/x86_64-w64-mingw32/4.6.3/include-fixed
c​:\strawberry-perl-5.16.2.1-64bit-portable\c\bin\../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/include
c​:/strawberry-perl-5.16.2.1-64bit-portable/c/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../include
End of search list.
GNU C (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) version 4.6.3 (x86_64-w64-mingw32)
  compiled by GNU C version 4.6.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
GGC heuristics​: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum​: b018692f7f9432ec66ee8656e457dbb6
COLLECT_GCC_OPTIONS='-v' '-o' 't64.exe' '-mtune=generic' '-march=x86-64'
c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/bin/as.exe -o C​:\Users\cm\AppData
\Local\Temp\ccqdGOO7.o C​:\Users\cm\AppData\Local\Temp\ccj2g4q2.s
COMPILER_PATH=c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../libexec/gcc/x86_64-w64-mingw32/4.6.3/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/b
in/../libexec/gcc/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/bin/
LIBRARY_PATH=c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/..
/lib/gcc/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/;c​:/strawberr
y-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../lib/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/
x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/;c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../.
./../
COLLECT_GCC_OPTIONS='-v' '-o' 't64.exe' '-mtune=generic' '-march=x86-64'
c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../libexec/gcc/x86_64-w64-mingw32/4.6.3/collect2.exe --sysroot=c​:/gccbuild/prefix/mingw64 -m i386pep
-Bdynamic -o t64.exe c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/c
rt2.o c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/crtbegin.o -Lc​:/s
trawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3 -Lc​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc -Lc​:/st
rawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib -Lc​:/strawberry-perl-5.16.2.
1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../lib -Lc​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mi
ngw32/4.6.3/../../../../x86_64-w64-mingw32/lib -Lc​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../.. C​:\User
s\cm\AppData\Local\Temp\ccqdGOO7.o -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_eh
-lgcc -lmoldname -lmingwex -lmsvcrt c​:/strawberry-perl-5.16.2.1-64bit-portable/c/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw3
2/lib/../lib/crtend.o

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

G​:\testatoi>

On Linux :

[cm@​COS63 ~/badcarp]$ uname -a
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
[cm@​COS63 ~/badcarp]$ cat tatoi.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
  int x;
  errno = 99;
  x = atoi("123");
  printf("%d\n", errno);
}
[cm@​COS63 ~/badcarp]$ gcc -v tatoi.c
Using built-in specs.
Target​: x86_64-redhat-linux
Configured with​: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http​://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model​: posix
gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
COLLECT_GCC_OPTIONS='-v' '-mtune=generic'
/usr/libexec/gcc/x86_64-redhat-linux/4.4.6/cc1 -quiet -v tatoi.c -quiet -dumpbase tatoi.c -mtune=generic -auxbase tatoi -version -o /tmp/cc5Ms7XN.s
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.4.6/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../x86_64-redhat-linux/include"
#include "..." search starts here​:
#include <...> search starts here​:
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/include
/usr/include
End of search list.
GNU C (GCC) version 4.4.6 20120305 (Red Hat 4.4.6-4) (x86_64-redhat-linux)
  compiled by GNU C version 4.4.6 20120305 (Red Hat 4.4.6-4), GMP version 4.3.1, MPFR version 2.4.1.
GGC heuristics​: --param ggc-min-expand=98 --param ggc-min-heapsize=127561
Compiler executable checksum​: 854e07d94351919f11e46712af1095f6
COLLECT_GCC_OPTIONS='-v' '-mtune=generic'
as -V -Qy -o /tmp/cc98hzGk.o /tmp/cc5Ms7XN.s
GNU assembler version 2.20.51.0.2 (x86_64-redhat-linux) using BFD version version 2.20.51.0.2-5.34.el6 20100205
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.4.6/​:/usr/libexec/gcc/x86_64-redhat-linux/4.4.6/​:/usr/libexec/gcc/x86_64-redhat-linux/​:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/​:/usr/lib/gcc/x86_64-redhat-linux/​:/usr/libexec/gcc/x86_64-redhat-linux/4.4.6/​:/usr/libexec/gcc/x86_64-redhat-linux/​:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/​:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.4.6/​:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/​:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/​:/lib/../lib64/​:/usr/lib/../lib64/​:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../​:/lib/​:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-mtune=generic'
/usr/libexec/gcc/x86_64-redhat-linux/4.4.6/collect2 --eh-frame-hdr --build-id -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.6/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../.. /tmp/cc98hzGk.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.4.6/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crtn.o
[cm@​COS63 ~/badcarp]$ ./a.out
99
[cm@​COS63 ~/badcarp]$

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2013

From cm.perl@abtela.com

Microsoft Windows [version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Tous droits réservés.

..

G​:\perls\blead\git\win32>set PATH=g​:\SPPC\bin;%PATH%
G​:\perls\blead\git\win32>dmake CC_HOME=g​:\SPPC CFG=Debug
...
G​:\perls\blead\git\win32>g​:\mingw64\bin\gdb ..\perl.exe
GNU gdb (GDB) 7.1.90.20100730-cvs
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+​: GNU GPL version 3 or later <http​://gnu.org/licenses/gpl.html>
This is free software​: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-w64-mingw32".
For bug reporting instructions, please see​:
<http​://www.gnu.org/software/gdb/bugs/>...
Reading symbols from G​:\perls\blead\git\win32/..\perl.exe...done.
(gdb) run -e "$! = 99; my $a = q{x}; print qq{$a\n}; $a =~ s/(.)/$1/; print qq{$a\n}, 0+$!, qq{\n}"
Starting program​: G​:\perls\blead\git\win32/..\perl.exe -e "$! = 99; my $a = q{x}; print qq{$a\n}; $a =~ s/(.)/$1/; print qq{$a\n}, 0+$!, qq{\n}"
[New Thread 23144.0x46f0]
x
x
0

Program exited normally.
(gdb) br Perl_pp_subst
Breakpoint 1 at 0x635fae90​: file ..\pp_hot.c, line 2142.
(gdb) run -e "$! = 99; my $a = q{x}; print qq{$a\n}; $a =~ s/(.)/$1/; print qq{$a\n}, 0+$!, qq{\n}"
Starting program​: G​:\perls\blead\git\win32/..\perl.exe -e "$! = 99; my $a = q{x}; print qq{$a\n}; $a =~ s/(.)/$1/; print qq{$a\n}, 0+$!, qq{\n}"
[New Thread 12192.0x49c0]
x

Breakpoint 1, Perl_pp_subst (my_perl=0x7c7fe8) at ..\pp_hot.c​:2142
2142 {
(gdb) print _errno()
$1 = 8131376
(gdb) watch *(int*)8131376
Hardware watchpoint 2​: *(int*)8131376
(gdb) c
Continuing.
Hardware watchpoint 2​: *(int*)8131376

Old value = 99
New value = 0
0x000007fefe5c3869 in wcstoul () from C​:\Windows\system32\msvcrt.dll
(gdb) bt
#0 0x000007fefe5c3869 in wcstoul () from C​:\Windows\system32\msvcrt.dll
#1 0x0000000077845410 in ntdll!RtlGetLastNtStatus () from C​:\Windows\system32\ntdll.dll
#2 0x0000000000000000 in ?? ()
(gdb) s
Single stepping until exit from function wcstoul,
which has no line number information.
0x000007fefe5d2d18 in msvcrt!_wtof_l () from C​:\Windows\system32\msvcrt.dll
(gdb) s
Single stepping until exit from function msvcrt!_wtof_l,
which has no line number information.
0x000007fefe5c39a0 in wcstoul () from C​:\Windows\system32\msvcrt.dll
(gdb) s
Single stepping until exit from function wcstoul,
which has no line number information.
0x000007fefe5c3a26 in msvcrt!atol () from C​:\Windows\system32\msvcrt.dll
(gdb) s
Single stepping until exit from function msvcrt!atol,
which has no line number information.
Perl_magic_get (my_perl=0x7c7fe8, sv=0x1d848e0, mg=<value optimized out>) at ..\mg.c​:933
933 if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
(gdb) l
928 * Pre-threads, this was paren = atoi(GvENAME((const GV *)mg->mg_obj));
929 * XXX Does the new way break anything?
930 */
931 paren = atoi(mg->mg_ptr); /* $& is in [0] */
932 do_numbuf_fetch​:
933 if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
934 CALLREG_NUMBUF_FETCH(rx,paren,sv);
935 break;
936 }
937 sv_setsv(sv,&PL_sv_undef);
(gdb) bt
#0 Perl_magic_get (my_perl=0x7c7fe8, sv=0x1d848e0, mg=<value optimized out>) at ..\mg.c​:933
#1 0x0000000063554068 in Perl_mg_get (my_perl=0x7c7fe8, sv=0x1d848e0) at ..\mg.c​:201
#2 0x000000006368b5b5 in Perl_sv_2pv_flags (my_perl=0x7c7fe8, sv=0x1d848e0, lp=0x22f7e0, flags=34) at ..\sv.c​:2745
#3 0x00000000635fb6b9 in Perl_pp_subst (my_perl=0x7c7fe8) at ..\pp_hot.c​:2292
#4 0x000000006351e870 in Perl_runops_debug (my_perl=0x7c7fe8) at ..\dump.c​:2192
#5 0x000000006359c36a in S_run_body (my_perl=0x7c7fe8) at perl.c​:2423
#6 perl_run (my_perl=0x7c7fe8) at perl.c​:2339
#7 0x0000000063721bcb in RunPerl (argc=3, argv=0x7c2480, env=0x7c5ce0) at perllib.c​:270
#8 0x00000000004013ce in __tmainCRTStartup () at ../../../../src/mingw-w64-stable-2.x-r5421/mingw-w64-crt/crt/crtexe.c​:313
#9 0x00000000004014e8 in mainCRTStartup () at ../../../../src/mingw-w64-stable-2.x-r5421/mingw-w64-crt/crt/crtexe.c​:193
(gdb) c
Continuing.
x
0
Hardware watchpoint 2​: *(int*)8131376

Old value = 0
New value = -17891602
0x0000000077791a91 in ntdll!RtlIsValidHandle () from C​:\Windows\system32\ntdll.dll
(gdb) printf "%x\n", -17891602
feeefeee
(gdb) c
Continuing.

Program exited normally.
(gdb) q

G​:\perls\blead\git\win32>

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2013

From @bulk88

On Fri Jan 11 10​:36​:01 2013, cm.perl@​abtela.com wrote​:

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

Great work. I'm not sure what is the best way to fix it. My idea is,
write a Perl_my_atoi that is win32 specific and saves/restores errno.
Have it have the same prototype CRT atoi, pick CRT atoi or Perl_my_atoi
as a function pointer as a process global static in win32.c, (maybe
DllMain or Perl_win32_init or Perl_sys_intern_init) based on OS version
6 and up. No saving of errno overhead on older windowses then.

The other way mentioned was write implement atoi in a cross platform way
for all OSes.

Do some clibs have atoi written in ASM? which is faster, our/Perl's
portable version, or random or specific OS's clib's? How do localization
and utf8 play a role in atoi?

Questions and ideas for thought.
--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Aug 29, 2013

From @nwc10

On Fri, Jan 11, 2013 at 07​:34​:51PM +0100, Christian Millour wrote​:

Any use of $&lt;digits&gt; or (getting $&amp;) will reset errno (and thus $!)
because the <digits> 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

I've pushed a branch smoke-me/nicholas/match-vars-in-mg_len
which eliminates all of these from mg.c

It's wasteful to be doing the numeric conversion on every read.
However, this does replace the atoi() call there with a call to strtoul()
at compile time in gv.c, which will hit the same errno bug

Having had quite a good look at every instance of atoi(), I think that they
should not be wrapped - they should be replaced with strtol() or strtoul()

A lot of the code in regcomp.c is like this​:

  case '1'​: case '2'​: case '3'​: case '4'​: /* (?1) */
  case '5'​: case '6'​: case '7'​: case '8'​: case '9'​:
  RExC_parse--;
  parse_recursion​:
  num = atoi(RExC_parse);
  parse_start = RExC_parse - 1; /* MJD */
  if (*RExC_parse == '-')
  RExC_parse++;
  while (isDIGIT(*RExC_parse))
  RExC_parse++;
  if (*RExC_parse!=')')
  vFAIL("Expecting close bracket");

ie it's doing work twice - first time in atoi() to walk over the digits,
and then again in the parser. Replacing that with strtoul() would avoid
the double loop.

*All* the code using atoi() also ignores overflow. That's a bug.

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

Thanks. That was my first question and you have already answered it.
Does strtoul() also exhibit this?

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

As above, I think that it's a bug that overflow is ignored. So I think that
strtol() would be an seem like an option (but see below, for why I think it's
not)

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 ?

I suspect that the your code is faster because it's hard coded for base 10.

On Fri, Jan 11, 2013 at 11​:52​:41PM -0800, bulk88 via RT wrote​:

Do some clibs have atoi written in ASM? which is faster, our/Perl's
portable version, or random or specific OS's clib's? How do localization
and utf8 play a role in atoi?

On atoi(), the Open Group says​:

  The call atoi(str) shall be equivalent to​:

  (int) strtol(str, (char **)NULL, 10)

  except that the handling of errors may differ. If the value cannot be
  represented, the behavior is undefined.

http​://pubs.opengroup.org/onlinepubs/009695399/functions/atoi.html

and on strtol() they say

  In other than the C [CX] [Option Start] or POSIX [Option End] locales,
  other implementation-defined subject sequences may be accepted.

http​://pubs.opengroup.org/onlinepubs/009695399/functions/strtol.html

Given that we would want to be using strtol() to parse numbers roughly
s/\A\s*-?[0-9]+\z/, we don't want locale dependant separators (presumably
thousands separators - can anyone verify this?) to be valid if the user's
locale has them. We'd be in the same mess that we have with printf() and
friends - we don't want the user's locale undermining the documented
behaviour (or worse yet, injecting bugs which might have security
implications, if one piece of parsing code thinks that a number ends at the
last character matching [0-9], and another piece of parsing code continues
further and produces a much larger value)

So think that this rules out using strtol()

On Thu, Aug 29, 2013 at 02​:30​:00PM +0200, Christian Millour wrote​:

Le 29/08/2013 11​:29, Leon Timmermans a écrit :

On Thu, Aug 29, 2013 at 9​:02 AM, Father Chrysostomos via RT
<perlbug-followup@​perl.org <mailto​:perlbug-followup@​perl.org>> wrote​:

Still\, shouldn't we wrap atoi on non\-compliant systems?  Otherwise we
will just keep finding this bug elsewhere \(or not finding it and having
things fail\)\.

I agree. This is just waiting to bite us somewhere else.

I agree that the errno bug is going to bite us.
But I think that the "locale specific" stuff is going to bite us too.
And the undefined behaviour for ignoring overflow.

This mess is not Windows-specific BTW. So maybe the best solution for
the wrapper would be to use a different signature :

int Perl_atoi(char const *s, int * overflow_p) {
int olderr, res;
olderr = errno;
*overflow_p = 0; /* redundant on WIN 6+ */
res = atoi(s);
*overflow_p = errno;
errno = olderr;
return res;
}

possibly together with an optimized version for those users that do not
care about overflow :

int Perl_atoi_ignore_overflow(char const *s) {
int olderr, res;
olderr = errno;
res = atoi(s);
errno = olderr;
return res;
}

So that the responsibility to handle overflow would be put clearly in
the hands of the caller.

I think that we should completely avoid calling the native atoi() (and
strtol(), and strtoul()) because we would have to reset the numeric locale
on each call to be sure that it behaved as we wanted it.

This would allow Windows XS code to use the native atoi, warts and all,
and spell out the decisions taken wrt overflow in core uses of atoi
(e.g. in mg.c to parse numbered match vars and $&, in regcomp.c to parse
backrefs and quantifiers, in malloc.c, etc).

Agree. In as much as, I don't think that we should be wrapping it at all.
I think we should be using our own function (or functions) that do exactly
what we need, without action-at-a-distance thanks to locales, or using errno
to (unreliably and inefficiently) report errors.

I think that this is less effort than trying to wrap the existing C library
code, *and* get it right, for all corner cases, on all platforms. Given that
we don't actually need most of the corner cases. (eg bases other than 10)

Of course this is pretty disgusting (and there might be a much better
way to handle it) but the root objective, which is giving the end-users
a reliable access to errors so that thay can handle those, is a very
fundamental and worthy one. What we see here are unforeseen interactions

Agree.

Effectively what I think we need is something that implements base 10, as in

  strtol(str, &end, 10);

with a different overflow approach. I think that Perl_grok_number() *almost*
already does everything we need - the only problem that I can spot is that it
treats "0 but true" as a valid number. If we add a flag to the return status
which says whether that was found - ie

#define IS_NUMBER_ZERO_BUT_TRUE 0x40

then it can be used directly (or wrapped) to give what we need. Note that its
integer processing already avoids unnecessary overflow checks, by unrolling
the loop 9 times, as it takes 10 decimal digits to overflow a 32 bit UV.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Sep 2, 2013

From @nwc10

On Thu, Aug 29, 2013 at 02​:13​:58PM +0100, Nicholas Clark wrote​:

On Thu, Aug 29, 2013 at 02​:30​:00PM +0200, Christian Millour wrote​:

I think that we should completely avoid calling the native atoi() (and
strtol(), and strtoul()) because we would have to reset the numeric locale
on each call to be sure that it behaved as we wanted it.

This would allow Windows XS code to use the native atoi, warts and all,
and spell out the decisions taken wrt overflow in core uses of atoi
(e.g. in mg.c to parse numbered match vars and $&, in regcomp.c to parse
backrefs and quantifiers, in malloc.c, etc).

blead now no longer uses atoi() to parse number match vars and $& at lookup
time. But yes, this just moves the problem around a bit, as it uses
strtoul() at parse time for them.

Agree. In as much as, I don't think that we should be wrapping it at all.
I think we should be using our own function (or functions) that do exactly
what we need, without action-at-a-distance thanks to locales, or using errno
to (unreliably and inefficiently) report errors.

I think that this is less effort than trying to wrap the existing C library
code, *and* get it right, for all corner cases, on all platforms. Given that
we don't actually need most of the corner cases. (eg bases other than 10)

Effectively what I think we need is something that implements base 10, as in

strtol\(str\, &end\, 10\);

with a different overflow approach. I think that Perl_grok_number() *almost*
already does everything we need - the only problem that I can spot is that it
treats "0 but true" as a valid number. If we add a flag to the return status
which says whether that was found - ie

#define IS_NUMBER_ZERO_BUT_TRUE 0x40

then it can be used directly (or wrapped) to give what we need. Note that its
integer processing already avoids unnecessary overflow checks, by unrolling
the loop 9 times, as it takes 10 decimal digits to overflow a 32 bit UV.

Looking further, I think that I'm wrong. In that, all (or nearly all) of the
places that currently use atoi() are using it on a '\0' terminated string,
which they don't know the length of. Perl_grok_number() doesn't assume '\0'
termination, but requires that the length of the string is passed in. So you
can't call it in these cases without first doing a strlen(). Given that the
parser needed by atoi() etc will naturally terminate on a '\0', walking the
string once to find the '\0' and then again to find the digits is somewhat
silly.

So I think the best solution is a function which behaves somewhat like
strtoul(), but quite a bit more restrictive. Something like

  size_t Perl_not_sure_what_name(const char *str, char *const *endptr);

[but I might have got that *const * thing wrong]

which parses the '\0' terminated base 10 string matching /\A([0-9]+)/
(ie no optional leading whitespace is permitted, and no optional leading
sign)

returning

* (normally) the value, and a pointer to the first not-a-digit
* the max size_t, with *endptr set to NULL if the value overflows
* 0, with *endptr set to NULL if it fails to parse anything

and then refactor the code to call it, removing atoi(), strtol() and strtoul()
and adapting the above spec if I got something wrong.

It's unsigned because I think all use cases for the 3 functions are actually
for unsigned values, with one possible exception - setting PL_destruct_level
from PERL_DESTRUCT_LEVEL. So signed parsing can be implemented for that
locally.

Forbidding leading spaces and a plus sign will mean slight changes to what we
accept as values from environment variables, but I don't think that this will
break any existing code, as I really doubt that people write things like
PERL_MEM_LOG=' 3' ./perl ...

The advantage of forbidding them is that the end pointer can then be used to
eliminate parsing loops in (at least) regcomp.c, which currently call atoi(),
and next thing walk the string using isDIGIT() to figure out where atoi() go
to.

Use size_t because I think that in all use cases atoi() is currently being
used either for things that fit into an `int`, or things that are constrained
by memory, so using UV would mean a lot of needless 64 bit arithmetic on any
32 bit platform built with -Duse64bitint

Return 0 on parse failure and a very big size_t value on overflow because
quite a few users are only concerned with "is it non-zero" or "is it larger
than 2", so they don't actually need to worry about the error conditions.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Sep 2, 2013

From cm.perl@abtela.com

Le 02/09/2013 16​:30, Nicholas Clark a écrit :

So I think the best solution is a function which behaves somewhat like
strtoul(), ...

It's unsigned because I think all use cases for the 3 functions are actually
for unsigned values, with one possible exception - setting PL_destruct_level
from PERL_DESTRUCT_LEVEL. So signed parsing can be implemented for that
locally.

There is at least an other exception, specifically the recursive regexp
pattern (?-PARNO)

and unless you have modified regcomp.c, the following code would handle
a string beginning with "-1" to atoi when parsing (?-1) :

  case '-'​: /* (?-1) */
  if (!(RExC_parse[0] >= '1' && RExC_parse[0] <= '9')) {
  RExC_parse--; /* rewind to let it be handled later */
  goto parse_flags;
  }
  /*FALLTHROUGH */
  case '1'​: case '2'​: case '3'​: case '4'​: /* (?1) */
  case '5'​: case '6'​: case '7'​: case '8'​: case '9'​:
  RExC_parse--;
  parse_recursion​:
  num = atoi(RExC_parse);
  parse_start = RExC_parse - 1; /* MJD */

so you would have to implement explicit signed parsing there too.

Forbidding leading spaces and a plus sign will mean slight changes to what we
accept as values from environment variables, but I don't think that this will
break any existing code, as I really doubt that people write things like
PERL_MEM_LOG=' 3' ./perl ...

The advantage of forbidding them is that the end pointer can then be used to
eliminate parsing loops in (at least) regcomp.c, which currently call atoi(),
and next thing walk the string using isDIGIT() to figure out where atoi() go
to.

Use size_t because I think that in all use cases atoi() is currently being
used either for things that fit into an `int`, or things that are constrained
by memory, so using UV would mean a lot of needless 64 bit arithmetic on any
32 bit platform built with -Duse64bitint

Return 0 on parse failure and a very big size_t value on overflow because
quite a few users are only concerned with "is it non-zero" or "is it larger
than 2", so they don't actually need to worry about the error conditions.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Oct 17, 2013

From @nwc10

On Mon, Sep 02, 2013 at 07​:14​:29PM +0200, Christian Millour wrote​:

There is at least an other exception, specifically the recursive regexp
pattern (?-PARNO)

and unless you have modified regcomp.c, the following code would handle
a string beginning with "-1" to atoi when parsing (?-1) :

         case '\-'&#8203;: /\* \(?\-1\) \*/
             if \(\!\(RExC\_parse\[0\] >= '1' && RExC\_parse\[0\] \<= '9'\)\) \{
                 RExC\_parse\-\-; /\* rewind to let it be handled later \*/
                 goto parse\_flags;
             \}
             /\*FALLTHROUGH \*/
         case '1'&#8203;: case '2'&#8203;: case '3'&#8203;: case '4'&#8203;: /\* \(?1\) \*/
    case '5'&#8203;: case '6'&#8203;: case '7'&#8203;: case '8'&#8203;: case '9'&#8203;:
        RExC\_parse\-\-;
           parse\_recursion&#8203;:
    num = atoi\(RExC\_parse\);
           parse\_start = RExC\_parse \- 1; /\* MJD \*/

so you would have to implement explicit signed parsing there too.

Yes, good point. I missed that.
I think that it's still less complex over all to do explicit signed parsing
there too, than the other alternatives, such as increasing the number of new
library functions.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2014

From @khwilliamson

Blead now has removed all uses of atoi() and kin, thanks to Jarkko Hietaniemi. Does that mean we can close this ticket?

--
Karl Williamson

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2014

From cm.perl@abtela.com

Le 23/07/2014 07​:05, Karl Williamson via RT a écrit :

Blead now has removed all uses of atoi() and kin, thanks to Jarkko Hietaniemi. Does that mean we can close this ticket?

as the OP I have no objection.

I will note that my original issue was also cured by
cbd58ba (see #81586) and/or Carp-1.32,
which works on older perls by hiding the issue with atoi on Windows 6+.

Also the side discussion on require should move to #119555.

Best regards,

--Christian

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2014

From @khwilliamson

The original OP has agreed to close this
--
Karl Williamson

@p5pRT p5pRT closed this as completed Jul 23, 2014
@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2014

@khwilliamson - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant