[ python-Bugs-969574 ] BSD restartable signals not correctly disabled

SourceForge.net noreply at sourceforge.net
Wed Jun 9 09:00:00 EDT 2004


Bugs item #969574, was opened at 2004-06-09 22:59
Message generated for change (Tracker Item Submitted) made by Item Submitter
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=969574&group_id=5470

Category: Python Interpreter Core
Group: Platform-specific
Status: Open
Resolution: None
Priority: 5
Submitted By: Luke Mewburn (lukem)
Assigned to: Nobody/Anonymous (nobody)
Summary: BSD restartable signals not correctly disabled

Initial Comment:
I noticed a problem with some python scripts not
performing correctly when ^C (SIGINT) was pressed. I
managed to isolate it to the following test case:
    import sys
    foo=sys.stdin.read()

Once that's executed, you need to press ^C _twice_ for
KeyboardInterrupt to be raised; the first ^C is
ignored.  If you manually enter that into an
interactive python session this behaviour also occurs,
although it appears to function correctly if you run
the foo=sys.stdin.read() a second time (only  one ^C is
needed).

This occurs on NetBSD 1.6 and 2.0, with python 2.1, 2.2
and 2.3, configured with and without pthreads.  It also
occurs on FreeBSD 4.8 with python 2.2.2.  It does not
occur on various Linux systems I asked people to test
for me.

(I have a NetBSD problem report about this issue:
http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=24797
)

I traced the process and noticed that the read() system
call was being restarted when the first SIGINT was
received.  This hint, and the fact that Linux was
unaffected indicated that python was probably not
expecting restartable signal behaviour, and that
behaviour is the default in BSD systems for signal(3)
(but not sigaction(2) or the other POSIX signal calls).

After doing some research in the python 2.3.4 source it
appeared to me that the intent was to disable
restartable signals, but that was not what was
happening in practice.  I noticed the following code
issues:
  * not all code had been converted from using
signal(3) to PyOS_getsig() and PyOS_setsig().  This is
contrary to the HISTORY for python 2.0beta2.
  * siginterrupt(2) (an older BSD function) was being
used in places in an attempt to ensure that signals
were not restartable.  However, in some cases this
function was called _before_ signal(3)/PyOS_setsig(),
which would mean that the call may be ineffective if
PyOS_setsig() was implemented using signal(3) and not
sigaction(2)
   * PyOS_setsig() was using sigaction(2) suboptimally,
iand inheriting the sa_flags from the existing handler.
 If SA_RESTART happened to be already set for the
signal, it would be copied.

I provide the following patch, which does:
  * converts a few remaining signal(3) calls to
PyOS_setsig().  There should be none left in a build on
a UNIX system, although there may be on other systems.
 Converting any remaining calls to signal(3) is left as
an exercise :)
  * moves siginterrupt(2) to PyOS_setsig() when the
latter is implemented using signal(3) instead of
sigaction(2).
  * when implementing PyOS_setsig() in terms of
sigaction(2), use sigaction(2) in a more portable and
"common" manner that explicitly clears the flags for
the new handler, thus preventing SA_RESTART from being
implicitly copied.

With this patch applied, python passes all the same
regression tests as without it, and my test case now
exits on the first ^C as expected.

Also, it is possible that this patch may also fix other
outstanding signal issues on systems with BSD
restartable signal semantics.

Cheers,
Luke.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=969574&group_id=5470



More information about the Python-bugs-list mailing list