From: Kenneth Albanowski Date: Tue, 26 Nov 1996 10:40:50 +0000 (-0500) Subject: Reliable signal patch X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7b160dda90126187f14dbd829dee2bd8b9e86fde;p=p5sagit%2Fp5-mst-13.2.git Reliable signal patch Subject: reliable signal patch (was Re: Reliable signals) On Tue, 26 Nov 1996, Kenneth Albanowski wrote: > > I found that 2 places in perl still use unreliable signals: > > my_pclose() in util.c > > pp_system() in pp_sys.c > > > > Is this working as designed, or an omission? > I guess a new set of signal macros are needed, to reliably save and > restore signal settings. Here is a patch that accomplishes this. It replaces the rsignal construction in mg.c with a generalized set of functions: rsignal, rsignalsave, rsignalrestore, and rsignalstate. Note that global.sym is patched to accomodate the new globally accessible functions. They probably will be of use to XSUBs too. This was diffed from a slightly messy 5.003_08, but should apply acceptably over any 5.003_* series. p5p-msgid: --- diff --git a/global.sym b/global.sym index ca7240a..3ae801f 100644 --- a/global.sym +++ b/global.sym @@ -979,6 +979,10 @@ regnext regprop repeatcpy rninstr +rsignal +rsignalsave +rsignalstate +rsignalrestore runops safecalloc safemalloc diff --git a/mg.c b/mg.c index 8c678f4..6bc242a 100644 --- a/mg.c +++ b/mg.c @@ -634,46 +634,6 @@ MAGIC* mg; return 0; } -#ifdef HAS_SIGACTION -/* set up reliable signal() clone */ - -typedef void (*Sigfunc) _((int)); - -static -Sigfunc rsignal(signo,handler) -int signo; -Sigfunc handler; -{ - struct sigaction act,oact; - - act.sa_handler = handler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; -#ifdef SA_RESTART - act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ -#endif - if (sigaction(signo, &act, &oact) < 0) - return(SIG_ERR); - else - return(oact.sa_handler); -} - -#else - -/* ah well, so much for reliability */ - -#define rsignal(x,y) signal(x,y) - -#endif - -static sig_trapped; -static -Signal_t -sig_trap(signo) -int signo; -{ - sig_trapped++; -} int magic_getsig(sv,mg) SV* sv; @@ -686,15 +646,11 @@ MAGIC* mg; if(psig_ptr[i]) sv_setsv(sv,psig_ptr[i]); else { - void (*origsig) _((int)); - /* get signal state without losing signals */ - sig_trapped=0; - origsig = rsignal(i,sig_trap); - rsignal(i,origsig); - if(sig_trapped) - kill(getpid(),i); + Sighandler_t sigstate; + sigstate = rsignalstate(i); + /* cache state so we don't fetch it again */ - if(origsig == SIG_IGN) + if(sigstate == SIG_IGN) sv_setpv(sv,"IGNORE"); else sv_setsv(sv,&sv_undef); diff --git a/perl.h b/perl.h index f740c9a..770190d 100644 --- a/perl.h +++ b/perl.h @@ -1157,6 +1157,14 @@ I32 unlnk _((char*)); # endif #endif +typedef Signal_t (*Sighandler_t) _((int)); + +#ifdef HAS_SIGACTION +typedef struct sigaction Sigsave_t; +#else +typedef Sighandler_t Sigsave_t; +#endif + #define SCAN_DEF 0 #define SCAN_TR 1 #define SCAN_REPL 2 diff --git a/pp_sys.c b/pp_sys.c index d580fba..ab8b8e6 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -2856,8 +2856,7 @@ PP(pp_system) int childpid; int result; int status; - Signal_t (*ihand)(); /* place to save signal during system() */ - Signal_t (*qhand)(); /* place to save signal during system() */ + Sigsave_t ihand,qhand; /* place to save signals during system() */ #if (defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(OS2) if (SP - MARK == 1) { @@ -2877,13 +2876,13 @@ PP(pp_system) sleep(5); } if (childpid > 0) { - ihand = signal(SIGINT, SIG_IGN); - qhand = signal(SIGQUIT, SIG_IGN); + rsignalsave(SIGINT, SIG_IGN, &ihand); + rsignalsave(SIGQUIT, SIG_IGN, &qhand); do { result = wait4pid(childpid, &status, 0); } while (result == -1 && errno == EINTR); - (void)signal(SIGINT, ihand); - (void)signal(SIGQUIT, qhand); + (void)rsignalrestore(SIGINT, &ihand); + (void)rsignalrestore(SIGQUIT, &qhand); statusvalue = FIXSTATUS(status); if (result < 0) value = -1; diff --git a/proto.h b/proto.h index 3b89d99..98d9420 100644 --- a/proto.h +++ b/proto.h @@ -355,6 +355,10 @@ char* regnext _((char* p)); char* regprop _((char* op)); void repeatcpy _((char* to, char* from, I32 len, I32 count)); char* rninstr _((char* big, char* bigend, char* little, char* lend)); +Sighandler_t rsignal _((int, Sighandler_t)); +int rsignalsave _((int, Sighandler_t, Sigsave_t*)); +int rsignalrestore _((int, Sigsave_t*)); +Sighandler_t rsignalstate _((int)); int runops _((void)); #ifndef HAS_RENAME I32 same_dirent _((char* a, char* b)); diff --git a/util.c b/util.c index 22bda3f..da73b57 100644 --- a/util.c +++ b/util.c @@ -1778,13 +1778,116 @@ int newfd; } #endif +#ifdef HAS_SIGACTION + +Sighandler_t rsignal(signo,handler) +int signo; +Sighandler_t handler; +{ + struct sigaction act,oact; + + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_RESTART + act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ +#endif + if (sigaction(signo, &act, &oact) < 0) + return(SIG_ERR); + else + return(oact.sa_handler); +} + +int rsignalsave(signo, handler, save) +int signo; +Sighandler_t handler; +Sigsave_t *save; +{ + struct sigaction act; + + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_RESTART + act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ +#endif + return sigaction(signo, &act, save); +} + +int rsignalrestore(signo, save) +int signo; +Sigsave_t *save; +{ + return sigaction(signo, save, 0); +} + +Sighandler_t rsignalstate(signo) +int signo; +{ + struct sigaction oact; + if (sigaction(signo, 0, &oact)<0) + return (SIG_ERR); + else + return (oact.sa_handler); +} + +#else + +static int sig_trapped; + +static +Signal_t sig_trap(signo) +int signo; +{ + sig_trapped++; +} + +Sighandler_t rsignalstate(signo) +int signo; +{ + Sighandler_t oldsig; + sig_trapped=0; + oldsig = signal(signo, sig_trap); + signal(signo, oldsig); + if (sig_trapped) + kill(getpid(),signo); + + return oldsig; +} + +Sighandler_t rsignal(signo,handler) +int signo; +Sighandler_t handler; +{ + return signal(signo,handler); +} + +int rsignalsave(signo, handler, save) +int signo; +Sighandler_t handler; +Sigsave_t *save; +{ + *save = signal(signo,handler); + return (*save == SIG_ERR) ? -1 : 0; +} + +int rsignalrestore(signo, save) +int signo; +Sigsave_t *save; +{ + return (signal(signo, *save) == SIG_ERR) ? -1 : 0; +} + +#endif + + #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) \ && !defined(VMS) /* VMS' my_popen() is in VMS.c */ I32 my_pclose(ptr) PerlIO *ptr; { - Signal_t (*hstat)(), (*istat)(), (*qstat)(); + Sigsave_t hstat, istat, qstat; int status; SV **svp; int pid; @@ -1802,15 +1905,15 @@ PerlIO *ptr; #ifdef UTS if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */ #endif - hstat = signal(SIGHUP, SIG_IGN); - istat = signal(SIGINT, SIG_IGN); - qstat = signal(SIGQUIT, SIG_IGN); + rsignalsave(SIGHUP, SIG_IGN, &hstat); + rsignalsave(SIGINT, SIG_IGN, &istat); + rsignalsave(SIGQUIT, SIG_IGN, &qstat); do { pid = wait4pid(pid, &status, 0); } while (pid == -1 && errno == EINTR); - signal(SIGHUP, hstat); - signal(SIGINT, istat); - signal(SIGQUIT, qstat); + rsignalrestore(SIGHUP, &hstat); + rsignalrestore(SIGINT, &istat); + rsignalrestore(SIGQUIT, &qstat); return(pid < 0 ? pid : status); } #endif /* !DOSISH */