⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch16_18.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 16.17. Writing a Signal Handler (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:44:10Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"><LINKREL="prev"HREF="ch16_17.htm"TITLE="16.16. Temporarily Overriding a Signal Handler"><LINKREL="next"HREF="ch16_19.htm"TITLE="16.18. Catching Ctrl-C"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_17.htm"TITLE="16.16. Temporarily Overriding a Signal Handler"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 16.16. Temporarily Overriding a Signal Handler"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_19.htm"TITLE="16.18. Catching Ctrl-C"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 16.18. Catching Ctrl-C"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch16-18838">16.17. Writing a Signal Handler</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1000005585">Problem</A></H3><PCLASS="para">You want to write a subroutine that will be called whenever your program receives a signal.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1000005588">Solution</A></H3><PCLASS="para">A signal handler is just a subroutine. With some risk, you can do anything in a signal handler you'd do in any Perl subroutine, but the more you do, the riskier it gets.</P><PCLASS="para">Some systems require you to reinstall your signal handler after each signal:</P><PRECLASS="programlisting">$SIG{INT} = \&amp;got_int;sub got_int {    $SIG{INT} = \&amp;got_int;          # but not for SIGCHLD!    # ...}</PRE><PCLASS="para">Some systems restart blocking operations, such as reading data. In such cases, you must call <CODECLASS="literal">die</CODE> within the handler and trap it with <CODECLASS="literal">eval</CODE>:</P><PRECLASS="programlisting">my $interrupted = 0;sub got_int {    $interrupted = 1;    $SIG{INT} = 'DEFAULT';          # or 'IGNORE'    die;}eval {    $SIG{INT} = \&amp;got_int;    # ... long-running code that you don't want to restart};if ($interrupted) {    # deal with the signal}</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1000005614">Discussion</A></H3><PCLASS="para">Installing a custom signal handling subroutine is a lot like playing with fire. It may seem like a lot of fun, but, sooner or later, you're going to get burned unless you're exceedingly careful. By installing Perl code to deal with signals, you're exposing yourself to two dangers. First, few system library functions are re-entrant. If the signal interrupts while Perl is executing one function (like <ICLASS="filename">malloc </I>(3) or <ICLASS="filename">printf </I>(3)), and your signal handler then calls the same function again, you could get unpredictable behavior&nbsp;- often, a core dump. Second, Perl isn't itself re-entrant at the lowest levels. (Release 5.005 of Perl supports lightweight processes called <EMCLASS="emphasis">threads</EM><ACLASS="indexterm"NAME="ch16-idx-1000006559-0"></A>.) If the signal interrupts Perl while Perl is changing its own internal data structures, unpredictable behavior may result&nbsp;- usually random core dumps.</P><PCLASS="para">You have two options: be paranoid or be pragmatic. The paranoid approach is to do as little as possible in your signal handler, as exemplified by the <CODECLASS="literal">eval</CODE> and <CODECLASS="literal">die</CODE> code in the Solution&nbsp;- set a variable that already has a value, and then bail. Even this is cavalier for the true paranoiac, who avoids <CODECLASS="literal">die</CODE> in a handler because the system <EMCLASS="emphasis">is</EM> out to get you. The pragmatic approach is to say "I know the risks, but prefer the convenience," and to do anything you want in your signal handler.</P><PCLASS="para">Signals have been implemented in many different operating systems, often in slightly different flavors. The two situations where signal implementations vary the most are when a signal occurs when its signal handler is active (<ICLASS="firstterm">reliability</I>), and when a signal interrupts a blocking system call like <CODECLASS="literal">read</CODE> or <CODECLASS="literal">accept</CODE> (<ICLASS="firstterm">restarting</I>).</P><PCLASS="para">The initial implementation of signals was unreliable, meaning that while a handler was running, further occurrences of the same signal would cause the default action, likely aborting the program. Later systems addressed this (each in their own subtly different way, of course) by providing a way to block the delivery of further signals of that number until the handler has finished. If Perl detects that your system can use reliable signals, it generates the proper system calls to achieve this saner, safer behavior. You can use POSIX signals to block signal delivery at other times, as described in <ACLASS="xref"HREF="ch16_21.htm"TITLE="Blocking Signals">Recipe 16.20</A>.</P><PCLASS="para">For truly portable code, the paranoid programmer will assume the worst case (unreliable signals) and reinstall the signal handler manually, usually as the first statement in a function:</P><PRECLASS="programlisting">$SIG{INT} = \&amp;catcher;sub catcher {    $SIG{INT} = \&amp;catcher;    # ...}</PRE><PCLASS="para">In the special case of catching SIGCHLD, see <ACLASS="xref"HREF="ch16_20.htm"TITLE="Avoiding Zombie Processes">Recipe 16.19</A>. System V has bizarre behavior that can trip you up.</P><PCLASS="para">Use the Config module to find out whether you have reliable signals:</P><PRECLASS="programlisting">use Config;print &quot;Hurrah!\n&quot; if $Config{d_sigaction};</PRE><PCLASS="para">Just because you have reliable signals doesn't mean you automatically get reliable programs. But without them, you certainly won't.</P><PCLASS="para">The first implementation of signals interrupted slow system calls, functions that require the cooperation of other processes or device drivers. If a signal comes in while those system calls are still running, they (and their Perl counterparts) return an error value and set the error to EINTR, <CODECLASS="literal">&quot;Interrupted</CODE> <CODECLASS="literal">system</CODE> <CODECLASS="literal">call&quot;</CODE>. Checking for this condition made programs so complicated that most didn't check, and therefore misbehaved or died if a signal interrupted a slow system call. Most modern versions of Unix allow you to change this behavior. Perl will always make system calls restartable if it is on a system that support it. If you have a POSIX system, you can control restarting using the POSIX module (see <ACLASS="xref"HREF="ch16_21.htm"TITLE="Blocking Signals">Recipe 16.20</A>).</P><PCLASS="para">To determine whether your interrupted system calls will automatically restart, look at your system's C <EMCLASS="emphasis">signal.h</EM> include file:</P><PRECLASS="programlisting">% egrep 'S[AV]_(RESTART|INTERRUPT)' /usr/include/*/signal.h</PRE><PCLASS="para">Two signals are untrappable and unignorable: SIGKILL and SIGSTOP. Full details of the signals available on your system and what they mean can be found in the <EMCLASS="emphasis">signal </EM>(3) manpage.<ACLASS="indexterm"NAME="ch16-idx-1000006398-0"></A><ACLASS="indexterm"NAME="ch16-idx-1000006398-1"></A><ACLASS="indexterm"NAME="ch16-idx-1000006398-2"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1000005645">See Also</A></H3><PCLASS="para">The <ACLASS="olink"HREF="../prog/ch06_02.htm#PERL2-CH-6-SECT-2.1">"Signals"</A> sections in <ACLASS="olink"HREF="../prog/ch06_01.htm">Chapter 6</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A> and in <ICLASS="filename">perlipc </I>(1); your system's <ICLASS="filename">sigaction </I>(2), <ICLASS="filename">signal</I> (3), and <ICLASS="filename">kill</I> (2) manpages (if you have them). <EMCLASS="emphasis">Porting UNIX Software</EM>, by Greg Lehey, O'Reilly &amp; Associates, (1995); <CITECLASS="citetitle">Advanced Programming in the Unix Environment</CITE></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_17.htm"TITLE="16.16. Temporarily Overriding a Signal Handler"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 16.16. Temporarily Overriding a Signal Handler"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_19.htm"TITLE="16.18. Catching Ctrl-C"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 16.18. Catching Ctrl-C"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">16.16. Temporarily Overriding a Signal Handler</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">16.18. Catching Ctrl-C</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -