summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Albanowski <kjahds@kjahds.com>1996-11-26 05:40:50 -0500
committerChip Salzenberg <chip@atlantic.net>1996-11-30 05:31:00 +1200
commit7b160dda90126187f14dbd829dee2bd8b9e86fde (patch)
tree81d158411bf7c946f7b4688ce96940589d187d49
parenteff9c6e2f5bda63e4dc69fc15e237a9843954369 (diff)
downloadperl-7b160dda90126187f14dbd829dee2bd8b9e86fde.tar.gz
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: <Pine.LNX.3.93.961126053209.294J-100000@kjahds.com>
-rw-r--r--global.sym4
-rw-r--r--mg.c52
-rw-r--r--perl.h8
-rw-r--r--pp_sys.c11
-rw-r--r--proto.h4
-rw-r--r--util.c117
6 files changed, 135 insertions, 61 deletions
diff --git a/global.sym b/global.sym
index ca7240a126..3ae801fcac 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 8c678f4e81..6bc242a77f 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 f740c9aa16..770190dd4c 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 d580fba438..ab8b8e6ded 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 3b89d9965d..98d9420706 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 22bda3fb09..da73b5784c 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 */