save errno/$! across Win32.pm autoloads too
authorTony Cook <tony@develop-help.com>
Wed, 19 Feb 2014 04:12:31 +0000 (15:12 +1100)
committerTony Cook <tony@develop-help.com>
Wed, 19 Feb 2014 04:40:34 +0000 (15:40 +1100)
ext/Win32CORE/Win32CORE.c
ext/Win32CORE/t/win32core.t

index bd9834e..91759e8 100644 (file)
 
 
 XS(w32_CORE_all){
+    /* I'd use dSAVE_ERRNO() here, but it doesn't save the Win32 error code
+     * under cygwin, if that changes this code should change to use that.
+     */
+    int saved_errno = errno;
     DWORD err = GetLastError();
     /* capture the XSANY value before Perl_load_module, the CV's any member will
      * be overwritten by Perl_load_module and subsequent newXSes or pure perl
@@ -31,6 +35,7 @@ XS(w32_CORE_all){
     const char *function  = (const char *) XSANY.any_ptr;
     Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvn("Win32",5), newSVnv(0.27));
     SetLastError(err);
+    errno = saved_errno;
     /* mark and SP from caller are passed through unchanged */
     call_pv(function, GIMME_V);
 }
index 64f2e95..8ef8cd0 100644 (file)
@@ -10,7 +10,7 @@ BEGIN {
        }
     }
 
-    plan tests => 5;
+    plan tests => 6;
 };
 use_ok( "Win32CORE" );
 
@@ -19,7 +19,9 @@ ok(!defined &Win32::ExpandEnvironmentStrings,
    "ensure other Win32::* functions aren't loaded yet");
 
 $^E = 42;
+$! = 4;
 ok(eval { Win32::GetLastError(); 1 }, 'GetLastError() works on the first call');
+my $errno = 0 + $!;
 my $sys_errno = 0 + $^E;
 SKIP: {
     $^O eq "cygwin"
@@ -28,6 +30,7 @@ SKIP: {
     # should not affect the last error being retrieved
     is($sys_errno, 42, '$^E is preserved across Win32 autoload');
 }
+is($errno, 4, '$! is preserved across Win32 autoload');
 
 # Now all Win32::* functions should be loaded
 ok(defined &Win32::ExpandEnvironmentStrings,