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

select returns -1 but $! is 0 (or empty string) #11160

Closed
p5pRT opened this issue Feb 28, 2011 · 14 comments
Closed

select returns -1 but $! is 0 (or empty string) #11160

p5pRT opened this issue Feb 28, 2011 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 28, 2011

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

Searchable as RT85104$

@p5pRT
Copy link
Author

p5pRT commented Feb 28, 2011

From oskar@osk.mine.nu

This is a bug report for perl from oskar@​osk.mine.nu,
generated with the help of perlbug 1.39 running under perl 5.10.1.


The program shows how select in some situations fails and return -1 but does not set $!.
On my machine it prints​:


waitpid=0

select=-1 errno=0
select=0


(Sometimes waitpid return >0 in which case this bug is not reproduced.
I was unable to fix that though.)

Here is the program - I tried to make it as short as possible.


#!/usr/bin/perl -w
pipe my $rh, my $wh or die "pipe​: $!\n";
my $pid = fork() // die "fork​: $!\n";
if ($pid == 0) {
  open (STDIN, '<&', $rh) or warn "dup2​: $!\n";
  exec "cat";
}
$SIG{'CHLD'} = sub { syswrite(STDOUT, "\n", 1); };
select(undef, undef, undef, 1);
close $wh;
print "waitpid=", waitpid($pid, 1), "\n";
my $f = select(undef,undef,undef,1);
print "select=$f errno=", int $!, "\n";
print "select=", scalar select(undef,undef,undef,1), "\n";


I did some debugging and it seems the select syscall actually
return -1 and sets errno to 4 (EINTR).
If you try it with strace though, it might say select returns
with ERESTARTNOHAND. I think that is due to strace/kernel internals.
This debugging solution showed that select returned EINTR​:


/* compile with gcc -shared -o fake_select.so fake_select.c -fPIC */
/* use with LD_PRELOAD=$PWD/fake_select.so program */

#define _GNU_SOURCE
#include <sys/select.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
  static int (*real_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) = NULL;
  if (!real_select)
  real_select = dlsym(RTLD_NEXT, "select");
  int result = real_select(nfds, readfds, writefds, exceptfds, timeout);
  int old_errno = errno;
  printf("c select=%d errno=%d strerror=%s\n", result, errno, strerror(errno));
  errno = old_errno;
  return result;
}


Regards,

Oskar Liljeblad



Flags​:
  category=core
  severity=low


Site configuration information for perl 5.10.1​:

Configured by Debian Project at Fri Jan 7 12​:14​:33 UTC 2011.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:
 
  Platform​:
  osname=linux, osvers=2.6.32-5-amd64, archname=x86_64-linux-gnu-thread-multi
  uname='linux madeleine 2.6.32-5-amd64 #1 smp fri dec 10 15​:35​:08 utc 2010 x86_64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.10.1 -Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.1 -Dd_dosuid -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.4.5', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
  libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
  perllibs=-ldl -lm -lpthread -lc -lcrypt
  libc=/lib/libc-2.11.2.so, so=so, useshrplib=true, libperl=libperl.so.5.10.1
  gnulibc_version='2.11.2'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches​:
  DEBPKG​:debian/arm_thread_stress_timeout - http​://bugs.debian.org/501970 Raise the timeout of ext/threads/shared/t/stress.t to accommodate slower build hosts
  DEBPKG​:debian/cpan_config_path - Set location of CPAN​::Config to /etc/perl as /usr may not be writable.
  DEBPKG​:debian/cpan_definstalldirs - Provide a sensible INSTALLDIRS default for modules installed from CPAN.
  DEBPKG​:debian/db_file_ver - http​://bugs.debian.org/340047 Remove overly restrictive DB_File version check.
  DEBPKG​:debian/doc_info - Replace generic man(1) instructions with Debian-specific information.
  DEBPKG​:debian/enc2xs_inc - http​://bugs.debian.org/290336 Tweak enc2xs to follow symlinks and ignore missing @​INC directories.
  DEBPKG​:debian/errno_ver - http​://bugs.debian.org/343351 Remove Errno version check due to upgrade problems with long-running processes.
  DEBPKG​:debian/extutils_hacks - Various debian-specific ExtUtils changes
  DEBPKG​:debian/fakeroot - Postpone LD_LIBRARY_PATH evaluation to the binary targets.
  DEBPKG​:debian/instmodsh_doc - Debian policy doesn't install .packlist files for core or vendor.
  DEBPKG​:debian/ld_run_path - Remove standard libs from LD_RUN_PATH as per Debian policy.
  DEBPKG​:debian/libnet_config_path - Set location of libnet.cfg to /etc/perl/Net as /usr may not be writable.
  DEBPKG​:debian/m68k_thread_stress - http​://bugs.debian.org/495826 Disable some threads tests on m68k for now due to missing TLS.
  DEBPKG​:debian/mod_paths - Tweak @​INC ordering for Debian
  DEBPKG​:debian/module_build_man_extensions - http​://bugs.debian.org/479460 Adjust Module​::Build manual page extensions for the Debian Perl policy
  DEBPKG​:debian/perl_synopsis - http​://bugs.debian.org/278323 Rearrange perl.pod
  DEBPKG​:debian/prune_libs - http​://bugs.debian.org/128355 Prune the list of libraries wanted to what we actually need.
  DEBPKG​:debian/use_gdbm - Explicitly link against -lgdbm_compat in ODBM_File/NDBM_File.
  DEBPKG​:fixes/assorted_docs - http​://bugs.debian.org/443733 [384f06a] Math​::BigInt​::CalcEmu documentation grammar fix
  DEBPKG​:fixes/net_smtp_docs - http​://bugs.debian.org/100195 [rt.cpan.org #36038] Document the Net​::SMTP 'Port' option
  DEBPKG​:fixes/processPL - http​://bugs.debian.org/357264 [rt.cpan.org #17224] Always use PERLRUNINST when building perl modules.
  DEBPKG​:debian/perlivp - http​://bugs.debian.org/510895 Make perlivp skip include directories in /usr/local
  DEBPKG​:fixes/pod2man-index-backslash - http​://bugs.debian.org/521256 Escape backslashes in .IX entries
  DEBPKG​:debian/disable-zlib-bundling - Disable zlib bundling in Compress​::Raw​::Zlib
  DEBPKG​:fixes/kfreebsd_cppsymbols - http​://bugs.debian.org/533098 [3b910a0] Add gcc predefined macros to $Config{cppsymbols} on GNU/kFreeBSD.
  DEBPKG​:debian/cpanplus_definstalldirs - http​://bugs.debian.org/533707 Configure CPANPLUS to use the site directories by default.
  DEBPKG​:debian/cpanplus_config_path - Save local versions of CPANPLUS​::Config​::System into /etc/perl.
  DEBPKG​:fixes/kfreebsd-filecopy-pipes - http​://bugs.debian.org/537555 [16f708c] Fix File​::Copy​::copy with pipes on GNU/kFreeBSD
  DEBPKG​:fixes/anon-tmpfile-dir - http​://bugs.debian.org/528544 [perl #66452] Honor TMPDIR when open()ing an anonymous temporary file
  DEBPKG​:fixes/abstract-sockets - http​://bugs.debian.org/329291 [89904c0] Add support for Abstract namespace sockets.
  DEBPKG​:fixes/hurd_cppsymbols - http​://bugs.debian.org/544307 [eeb92b7] Add gcc predefined macros to $Config{cppsymbols} on GNU/Hurd.
  DEBPKG​:fixes/autodie-flock - http​://bugs.debian.org/543731 Allow for flock returning EAGAIN instead of EWOULDBLOCK on linux/parisc
  DEBPKG​:fixes/archive-tar-instance-error - http​://bugs.debian.org/539355 [rt.cpan.org #48879] Separate Archive​::Tar instance error strings from each other
  DEBPKG​:fixes/positive-gpos - http​://bugs.debian.org/545234 [perl #69056] [c584a96] Fix \\G crash on first match
  DEBPKG​:debian/devel-ppport-ia64-optim - http​://bugs.debian.org/548943 Work around an ICE on ia64
  DEBPKG​:fixes/trie-logic-match - http​://bugs.debian.org/552291 [perl #69973] [0abd0d7] Fix a DoS in Unicode processing [CVE-2009-3626]
  DEBPKG​:fixes/hppa-thread-eagain - http​://bugs.debian.org/554218 make the threads-shared test suite more robust, fixing failures on hppa
  DEBPKG​:fixes/crash-on-undefined-destroy - http​://bugs.debian.org/564074 [perl #71952] [1f15e67] Fix a NULL pointer dereference when looking for a DESTROY method
  DEBPKG​:fixes/tainted-errno - http​://bugs.debian.org/574129 [perl #61976] [be1cf43] fix an errno stringification bug in taint mode
  DEBPKG​:fixes/safe-upgrade - http​://bugs.debian.org/582978 Upgrade Safe.pm to 2.25, fixing CVE-2010-1974
  DEBPKG​:fixes/tell-crash - http​://bugs.debian.org/578577 [f4817f3] Fix a tell() crash on bad arguments.
  DEBPKG​:fixes/format-write-crash - http​://bugs.debian.org/579537 [perl #22977] [421f30e] Fix a crash in format/write
  DEBPKG​:fixes/arm-alignment - http​://bugs.debian.org/289884 [f1c7503] Prevent gcc from optimizing the alignment test away on armel
  DEBPKG​:fixes/fcgi-test - Fix a failure in CGI/t/fast.t when FCGI is installed
  DEBPKG​:fixes/hurd-ccflags - http​://bugs.debian.org/587901 Make hints/gnu.sh append to $ccflags rather than overriding them
  DEBPKG​:debian/squelch-locale-warnings - http​://bugs.debian.org/508764 Squelch locale warnings in Debian package maintainer scripts
  DEBPKG​:fixes/lc-numeric-docs - http​://bugs.debian.org/379329 [perl #78452] [903eb63] LC_NUMERIC documentation fixes
  DEBPKG​:fixes/lc-numeric-sprintf - http​://bugs.debian.org/601549 [perl #78632] [b3fd614] Fix sprintf not to ignore LC_NUMERIC with constants
  DEBPKG​:fixes/concat-stack-corruption - http​://bugs.debian.org/596105 [perl #78674] [e3393f5] Fix stack pointer corruption in pp_concat() with 'use encoding'
  DEBPKG​:fixes/cgi-multiline-header - http​://bugs.debian.org/606995 [CVE-2010-2761 CVE-2010-4410 CVE-2010-4411] CGI.pm MIME boundary and multiline header vulnerabilities
  DEBPKG​:patchlevel - http​://bugs.debian.org/567489 List packaged patches for 5.10.1-17 in patchlevel.h


@​INC for perl 5.10.1​:
  /home/usel/sys/lib/perl
  /etc/perl
  /usr/local/lib/perl/5.10.1
  /usr/local/share/perl/5.10.1
  /usr/lib/perl5
  /usr/share/perl5
  /usr/lib/perl/5.10
  /usr/share/perl/5.10
  /usr/local/lib/site_perl
  /usr/local/lib/perl/5.10.0
  /usr/local/share/perl/5.10.0
  .


Environment for perl 5.10.1​:
  HOME=/home/usel
  LANG=POSIX
  LANGUAGE (unset)
  LC_CTYPE=en_US.UTF-8
  LD_LIBRARY_PATH=/home/usel/sys/lib
  LOGDIR (unset)
  PATH=.​:/home/usel/sys/bin​:/usr/local/bin​:/usr/bin​:/bin​:/usr/games
  PERLLIB=/home/usel/sys/lib/perl
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From perl5-porters@ton.iguana.be

In article <rt-3.6.HEAD-28241-1298911559-101.85104-75-0@​perl.org>,
  "oskar@​osk.mine.nu (via RT)" <perlbug-followup@​perl.org> writes​:

-----------------------------------------------------------------
The program shows how select in some situations fails and return -1 but does not set $!.
On my machine it prints​:

---
waitpid=0

select=-1 errno=0
select=0
---

(Sometimes waitpid return >0 in which case this bug is not reproduced.
I was unable to fix that though.)

Here is the program - I tried to make it as short as possible.

---
#!/usr/bin/perl -w
pipe my $rh, my $wh or die "pipe​: $!\n";
my $pid = fork() // die "fork​: $!\n";
if ($pid == 0) {
open (STDIN, '<&', $rh) or warn "dup2​: $!\n";
exec "cat";
}
$SIG{'CHLD'} = sub { syswrite(STDOUT, "\n", 1); };
select(undef, undef, undef, 1);
close $wh;
print "waitpid=", waitpid($pid, 1), "\n";
my $f = select(undef,undef,undef,1);
print "select=$f errno=", int $!, "\n";
print "select=", scalar select(undef,undef,undef,1), "\n";
---

I did some debugging and it seems the select syscall actually
return -1 and sets errno to 4 (EINTR).
If you try it with strace though, it might say select returns
with ERESTARTNOHAND. I think that is due to strace/kernel internals.
This debugging solution showed that select returned EINTR​:

This is the annoying result of the way safe signals work. Basically on the
real interrupt perl only sets a flag and your signal handler is only called
later, with $! already set to the result errno. Doing the system call in the
handler destroys your $!. You can easily fix your problem by doing​:

$SIG{'CHLD'} = sub { local $!; syswrite(STDOUT, "\n", 1); };

However, i don't think you SHOULD have to do this. To my mind perl itself
should save $! and $^E (and possibly also $@​) when it delayed dispatches
an interrupt callback (which can happen at any time, not just during
slow system calls)

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

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

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From perl5-porters@ton.iguana.be

In article <ikiitc$k2b$1@​post.home.lunix>,
  perl5-porters@​ton.iguana.be (Ton Hospel) writes​:

In article <rt-3.6.HEAD-28241-1298911559-101.85104-75-0@​perl.org>,
"oskar@​osk.mine.nu (via RT)" <perlbug-followup@​perl.org> writes​:

-----------------------------------------------------------------
The program shows how select in some situations fails and return -1 but does not set $!.
On my machine it prints​:

---
waitpid=0

select=-1 errno=0
select=0
---

(Sometimes waitpid return >0 in which case this bug is not reproduced.
I was unable to fix that though.)

Here is the program - I tried to make it as short as possible.

---
#!/usr/bin/perl -w
pipe my $rh, my $wh or die "pipe​: $!\n";
my $pid = fork() // die "fork​: $!\n";
if ($pid == 0) {
open (STDIN, '<&', $rh) or warn "dup2​: $!\n";
exec "cat";
}
$SIG{'CHLD'} = sub { syswrite(STDOUT, "\n", 1); };
select(undef, undef, undef, 1);
close $wh;
print "waitpid=", waitpid($pid, 1), "\n";
my $f = select(undef,undef,undef,1);
print "select=$f errno=", int $!, "\n";
print "select=", scalar select(undef,undef,undef,1), "\n";
---

I did some debugging and it seems the select syscall actually
return -1 and sets errno to 4 (EINTR).
If you try it with strace though, it might say select returns
with ERESTARTNOHAND. I think that is due to strace/kernel internals.
This debugging solution showed that select returned EINTR​:

This is the annoying result of the way safe signals work. Basically on the
real interrupt perl only sets a flag and your signal handler is only called
later, with $! already set to the result errno. Doing the system call in the
handler destroys your $!. You can easily fix your problem by doing​:

$SIG{'CHLD'} = sub { local $!; syswrite(STDOUT, "\n", 1); };

However, i don't think you SHOULD have to do this. To my mind perl itself
should save $! and $^E (and possibly also $@​) when it delayed dispatches
an interrupt callback (which can happen at any time, not just during
slow system calls)

And here is a patch that saves $! end $^E (not doing $@​ in case the user
wants to die in the handler which is perfectly reasonable). The restore of
$^E on non UNIX systems is completely untested, the code is stolen from
magig_get and magic_set, I have no idea if it works or even compiles.

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

Inline Patch
--- /home/ton/src/perl-5.10.1/mg.c	2009-05-26 23:20:38.000000000 +0200
+++ mg.c	2011-03-01 12:37:13.301519305 +0100
@@ -1415,8 +1417,28 @@
 Perl_despatch_signals(pTHX)
 {
     dVAR;
+    dSAVEDERRNO;
     int sig;
+
+    /* Save $^E by Duplicating some code from Perl_magic_get and Perl_magic_set
+       VAX and unix are already handled by SAVED ERRNO */
+#if defined(MACOS_TRADITIONAL)
+    const short saved_err = gMacPerl_OSErr;
+#elif defined(OS2)
+    int saved_err;
+    if ((_emx_env & 0x200) && errno != errno_isOS2) {
+	const int tmp = _syserrno();
+	if (tmp)	/* 2nd call to _syserrno() makes it 0 */
+	    Perl_rc = tmp;
+    }
+    saved_err = Perl_rc;
+#elif defined(WIN32)
+    const DWORD saved_err = GetLastError();
+#endif
+
+    SAVE_ERRNO;
     PL_sig_pending = 0;
+
     for (sig = 1; sig < SIG_SIZE; sig++) {
 	if (PL_psig_pend[sig]) {
 	    PERL_BLOCKSIG_ADD(set, sig);
@@ -1428,6 +1450,17 @@
 	    (*PL_sighandlerp)(sig);
 #endif
 	    PERL_BLOCKSIG_UNBLOCK(set);
+
+	    /* Restore $! and $^E for the next signal or the caller */
+	    RESTORE_ERRNO;
+#if defined(MACOS_TRADITIONAL)
+	    gMacPerl_OSErr = saved_err;
+#elif defined(OS2)
+	    Perl_rc = saved_err;
+	    os2_setsyserrno(Perl_rc);
+#elif defined(WIN32)
+	    SetLastError(saved_err);
+#endif
 	}
     }
 }
==========================================================================

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From @Leont

On Tue, Mar 1, 2011 at 11​:48 AM, Ton Hospel <perl5-porters@​ton.iguana.be> wrote​:

In article <rt-3.6.HEAD-28241-1298911559-101.85104-75-0@​perl.org>,
       "oskar@​osk.mine.nu (via RT)" <perlbug-followup@​perl.org> writes​:
This is the annoying result of the way safe signals work. Basically on the
real interrupt perl only sets a flag and your signal handler is only called
later, with $! already set to the result errno. Doing the system call in the
handler destroys your $!. You can easily fix your problem by doing​:

$SIG{'CHLD'} = sub { local $!; syswrite(STDOUT, "\n", 1); };

However, i don't think you SHOULD have to do this. To my mind perl itself
should save $! and $^E (and possibly also $@​) when it delayed dispatches
an interrupt callback (which can happen at any time, not just during
slow system calls)

Actually, blead already does this (see commit
d016601).

Leon

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From @Leont

On Tue, Mar 1, 2011 at 2​:29 PM, Ton Hospel <perl5-porters@​ton.iguana.be> wrote​:

And here is a patch that saves $! end $^E (not doing $@​ in case the user
wants to die in the handler which is perfectly reasonable). The restore of
$^E on non UNIX systems is completely untested, the code is stolen from
magig_get and magic_set, I have no idea if it works or even compiles.

Next time please send a patch against blead, not such an old release
of perl. It can't be applied because that function has changed quite a
bit since that time. The current code does not save $^E though, so
that part may be interesting (but too late to make it in 5.14 I
think).

Leon

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From perl5-porters@ton.iguana.be

In article <AANLkTimMGcg3qH_8OyShXmiqEcGw9GePTB-butjtRzyy@​mail.gmail.com>,
  Leon Timmermans <fawaka@​gmail.com> writes​:

On Tue, Mar 1, 2011 at 11​:48 AM, Ton Hospel <perl5-porters@​ton.iguana.be> wrote​:

In article <rt-3.6.HEAD-28241-1298911559-101.85104-75-0@​perl.org>,
       "oskar@​osk.mine.nu (via RT)" <perlbug-followup@​perl.org> writes​:
This is the annoying result of the way safe signals work. Basically on the
real interrupt perl only sets a flag and your signal handler is only called
later, with $! already set to the result errno. Doing the system call in the
handler destroys your $!. You can easily fix your problem by doing​:

$SIG{'CHLD'} = sub { local $!; syswrite(STDOUT, "\n", 1); };

However, i don't think you SHOULD have to do this. To my mind perl itself
should save $! and $^E (and possibly also $@​) when it delayed dispatches
an interrupt callback (which can happen at any time, not just during
slow system calls)

Actually, blead already does this (see commit
d016601).

Leon

Ah, good. I guess i'll have to start using git to see blead...

...fetching git and a git copy of blead and looking at that commit....

But actually I like my patch (in this same thread) slightly better.
- It only saves errno once even if there are multiple signals to be
  dispatched (but still restores at the end of each so multiple signals
  handlers always see the initial $!)
  (on the other hand, this is an extremely minor optimization)
- It also saves $^E
  (On the other hand, $^E for current perls is probably only important on
  windows, but I don't know if there you actually have real signals that
  run "suddenly")

Ps​: why is the function called Perl_despatch_signals instead of
  Perl_dispatch_signals ? Looking it up I just learned that despatch is
  actually the proper spelling in British English, but all other places
  in the perl source code use dispatch...

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2011

From perl5-porters@ton.iguana.be

In article <AANLkTimprXWyhpLz+nRs_Cx2ZYw9tsgCrwDfUVAm7EHD@​mail.gmail.com>,
  Leon Timmermans <fawaka@​gmail.com> writes​:

Next time please send a patch against blead, not such an old release
of perl. It can't be applied because that function has changed quite a
bit since that time. The current code does not save $^E though, so
that part may be interesting (but too late to make it in 5.14 I
think).

Leon

Ok following is the patch against blead. Changes​:
  - Only save errno once before calling a signal handler
  (but restore at the end of each handler)
  - Also save $^E

I have no system where $^E differs from $!, so it's pretty much untested.
So it doesn't belong in 5.14 anyways until it has been smoked on some
different platforms. Someone who knows these platforms should also be the one
to add a test (what is a valid system error number and how do you trigger
a signal on windows ?)


mg.c | 29 ++++++++++++++++++++++++++++-
1 files changed, 28 insertions(+), 1 deletions(-)

Inline Patch
diff --git a/mg.c b/mg.c
index 7b5fdf5..9f892a3 100644
--- a/mg.c
+++ b/mg.c
@@ -1446,11 +1446,30 @@ void
 Perl_despatch_signals(pTHX)
 {
     dVAR;
+    dSAVEDERRNO;
     int sig;
+
+    /* Save $^E by Duplicating some code from Perl_magic_get and Perl_magic_set
+       VAX and unix are already handled by SAVED ERRNO */
+#if defined(MACOS_TRADITIONAL)
+    const short saved_err = gMacPerl_OSErr;
+#elif defined(OS2)
+    int saved_err;
+
+    if ((_emx_env & 0x200) && errno != errno_isOS2) {
+	const int tmp = _syserrno();
+	if (tmp)	/* 2nd call to _syserrno() makes it 0 */
+	    Perl_rc = tmp;
+    }
+    saved_err = Perl_rc;
+#elif defined(WIN32)
+    const DWORD saved_err = GetLastError();
+#endif
+
+    SAVE_ERRNO;
     PL_sig_pending = 0;
     for (sig = 1; sig < SIG_SIZE; sig++) {
 	if (PL_psig_pend[sig]) {
-	    dSAVE_ERRNO;
 #ifdef HAS_SIGPROCMASK
 	    /* From sigaction(2) (FreeBSD man page):
 	     * | Signal routines normally execute with the signal that
@@ -1484,6 +1503,14 @@ Perl_despatch_signals(pTHX)
 		LEAVE;
 #endif
 	    RESTORE_ERRNO;
+#if defined(MACOS_TRADITIONAL)
+	    gMacPerl_OSErr = saved_err;
+#elif defined(OS2)
+	    Perl_rc = saved_err;
+	    os2_setsyserrno(Perl_rc);
+#elif defined(WIN32)
+	    SetLastError(saved_err);
+#endif
 	}
     }
 }
-- 
1.7.1

@p5pRT
Copy link
Author

p5pRT commented May 22, 2011

From @cpansprout

On Tue Mar 01 07​:44​:37 2011, perl5-porters@​ton.iguana.be wrote​:

In article
<AANLkTimprXWyhpLz+nRs_Cx2ZYw9tsgCrwDfUVAm7EHD@​mail.gmail.com>,
Leon Timmermans <fawaka@​gmail.com> writes​:

Next time please send a patch against blead, not such an old release
of perl. It can't be applied because that function has changed quite
a
bit since that time. The current code does not save $^E though, so
that part may be interesting (but too late to make it in 5.14 I
think).

Leon

Ok following is the patch against blead. Changes​:
- Only save errno once before calling a signal handler
(but restore at the end of each handler)
- Also save $^E

Your patch uses MACOS_TRADITIONAL. Mac Classic support was removed from
perl in 5.12, I think.

I have no system where $^E differs from $!, so it's pretty much
untested.
So it doesn't belong in 5.14 anyways until it has been smoked on some
different platforms. Someone who knows these platforms should also be
the one
to add a test (what is a valid system error number and how do you
trigger
a signal on windows ?)

---
mg.c | 29 ++++++++++++++++++++++++++++-
1 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/mg.c b/mg.c
index 7b5fdf5..9f892a3 100644
--- a/mg.c
+++ b/mg.c
@​@​ -1446,11 +1446,30 @​@​ void
Perl_despatch_signals(pTHX)
{
dVAR;
+ dSAVEDERRNO;
int sig;
+
+ /* Save $^E by Duplicating some code from Perl_magic_get and
Perl_magic_set
+ VAX and unix are already handled by SAVED ERRNO */
+#if defined(MACOS_TRADITIONAL)
+ const short saved_err = gMacPerl_OSErr;
+#elif defined(OS2)
+ int saved_err;
+
+ if ((_emx_env & 0x200) && errno != errno_isOS2) {
+ const int tmp = _syserrno();
+ if (tmp) /* 2nd call to _syserrno() makes it 0 */
+ Perl_rc = tmp;
+ }
+ saved_err = Perl_rc;
+#elif defined(WIN32)
+ const DWORD saved_err = GetLastError();
+#endif
+
+ SAVE_ERRNO;
PL_sig_pending = 0;
for (sig = 1; sig < SIG_SIZE; sig++) {
if (PL_psig_pend[sig]) {
- dSAVE_ERRNO;
#ifdef HAS_SIGPROCMASK
/* From sigaction(2) (FreeBSD man page)​:
* | Signal routines normally execute with the signal that
@​@​ -1484,6 +1503,14 @​@​ Perl_despatch_signals(pTHX)
LEAVE;
#endif
RESTORE_ERRNO;
+#if defined(MACOS_TRADITIONAL)
+ gMacPerl_OSErr = saved_err;
+#elif defined(OS2)
+ Perl_rc = saved_err;
+ os2_setsyserrno(Perl_rc);
+#elif defined(WIN32)
+ SetLastError(saved_err);
+#endif
}
}
}

@p5pRT
Copy link
Author

p5pRT commented Jun 24, 2013

From @tonycoz

On Tue Mar 01 07​:44​:37 2011, perl5-porters@​ton.iguana.be wrote​:

Ok following is the patch against blead. Changes​:
- Only save errno once before calling a signal handler
(but restore at the end of each handler)
- Also save $^E

While the patch supplied has some issues, I wonder if dSAVE_ERRNO should
save the Win32/OS/2 error codes in general?

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 15, 2013

From @tonycoz

On Sun Jun 23 22​:50​:30 2013, tonyc wrote​:

On Tue Mar 01 07​:44​:37 2011, perl5-porters@​ton.iguana.be wrote​:

Ok following is the patch against blead. Changes​:
- Only save errno once before calling a signal handler
(but restore at the end of each handler)
- Also save $^E

While the patch supplied has some issues, I wonder if dSAVE_ERRNO should
save the Win32/OS/2 error codes in general?

Here's an alternate patch that extends the errno save macros for
platforms other than VMS.

No tests yet.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 15, 2013

From @tonycoz

0001-perl-85104-work-harder-to-save-error-numbers.patch
From 2b38ee36b8f61351702be32738a3316707bf1c35 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Mon, 15 Jul 2013 10:42:01 +1000
Subject: [PATCH] [perl #85104] work harder to save error numbers

Updates the errno save macros to save the platform error number where
needed for more than just VMS.

The OS/2 code is untested.
---
 perl.h |   31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/perl.h b/perl.h
index bc8388f..a745c2b 100644
--- a/perl.h
+++ b/perl.h
@@ -1168,12 +1168,6 @@ EXTERN_C char *crypt(const char *, const char *);
 #   define SS_IVCHAN  		SS$_IVCHAN
 #   define SS_NORMAL  		SS$_NORMAL
 #else
-#   define SETERRNO(errcode,vmserrcode) (errno = (errcode))
-#   define dSAVEDERRNO    int saved_errno
-#   define dSAVE_ERRNO    int saved_errno = errno
-#   define SAVE_ERRNO     (saved_errno = errno)
-#   define RESTORE_ERRNO  (errno = saved_errno)
-
 #   define LIB_INVARG 		0
 #   define RMS_DIR    		0
 #   define RMS_FAC    		0
@@ -1188,6 +1182,31 @@ EXTERN_C char *crypt(const char *, const char *);
 #   define SS_NORMAL  		0
 #endif
 
+#ifdef WIN32
+#   define dSAVEDERRNO  int saved_errno; DWORD saved_win32_errno
+#   define dSAVE_ERRNO  int saved_errno = errno; DWORD saved_win32_errno = GetLastError()
+#   define SAVE_ERRNO   ( saved_errno = errno, saved_win32_errno = GetLastError() )
+#   define RESTORE_ERRNO ( errno = saved_errno, SetLastError(saved_win32_errno) )
+#endif
+
+#ifdef OS2
+#   define dSAVEDERRNO  int saved_errno; unsigned long saved_os2_errno
+#   define dSAVE_ERRNO  int saved_errno = errno; unsigned long saved_os2_errno = Perl_rc
+#   define SAVE_ERRNO   ( saved_errno = errno, saved_os2_errno = Perl_rc )
+#   define RESTORE_ERRNO ( errno = saved_errno, Perl_rc = saved_os2_errno) )
+#endif
+
+#ifndef SETERRNO
+#   define SETERRNO(errcode,vmserrcode) (errno = (errcode))
+#endif
+
+#ifndef dSAVEDERRNO
+#   define dSAVEDERRNO    int saved_errno
+#   define dSAVE_ERRNO    int saved_errno = errno
+#   define SAVE_ERRNO     (saved_errno = errno)
+#   define RESTORE_ERRNO  (errno = saved_errno)
+#endif
+
 #define ERRSV GvSVn(PL_errgv)
 
 #define CLEAR_ERRSV() STMT_START {					\
-- 
1.7.10.4

@p5pRT
Copy link
Author

p5pRT commented Aug 26, 2013

From @tonycoz

On Sun Jul 14 18​:10​:49 2013, tonyc wrote​:

On Sun Jun 23 22​:50​:30 2013, tonyc wrote​:

On Tue Mar 01 07​:44​:37 2011, perl5-porters@​ton.iguana.be wrote​:

Ok following is the patch against blead. Changes​:
- Only save errno once before calling a signal handler
(but restore at the end of each handler)
- Also save $^E

While the patch supplied has some issues, I wonder if dSAVE_ERRNO should
save the Win32/OS/2 error codes in general?

Here's an alternate patch that extends the errno save macros for
platforms other than VMS.

No tests yet.

I've applied a varient of this as
6ca940a with tests for win32 in
ed51a34.

Tony

@p5pRT
Copy link
Author

p5pRT commented Aug 26, 2013

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

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

No branches or pull requests

1 participant