Rework the timeout of the CGI script.

The previous implementation was fine to catch timeout of third-party
tools (like dot), but to good to catch timeout in Spot itself, because
Python will not deliver a SIGALRM while a native function (e.g. Spot's
translation) is running.  So we fork() the Python process, with a
parent that does nothing but wait for the termination of the child or
for an alarm.  On SIGALRM, the parent kills all children.

* wrap/python/ajax/spot.in: Adjust to fork.
* wrap/python/tests/alarm.py: New test file to test this
scenario in a more controled environment.
* wrap/python/tests/Makefile.am: Add it.
This commit is contained in:
Alexandre Duret-Lutz 2012-06-04 16:38:42 +02:00
parent 75862a3284
commit 7b7a946485
4 changed files with 86 additions and 7 deletions

View file

@ -220,16 +220,12 @@ If you want to benchmark big formulae it is
better to install Spot on your own computer.</p>\n""")
finish(kill = True)
def reset_alarm():
signal.alarm(30)
def run_dot(basename, ext):
outname = basename + '.' + ext
# Do not call "dot" to generate a file that already exists.
if not os.access(outname, os.F_OK):
os.spawnlp(os.P_WAIT, dot, dot, dot_bgcolor, '-T' + ext,
'-Gsize=8.2,8.2', '-o', outname, basename + '.txt')
reset_alarm()
# Create a unused hardlink that points to the output picture
# just to remember how many cache entries are sharing it.
os.link(outname, tmpdir + "/" + ext)
@ -344,8 +340,20 @@ if output_type == 'v':
spot.unblock_signal(signal.SIGALRM)
spot.unblock_signal(signal.SIGTERM)
os.setpgrp()
signal.signal(signal.SIGALRM, alarm_handler)
reset_alarm()
child = os.fork()
if child != 0:
# In parent. We are just waiting for the termination of the
# child, or for the timeout alarm. On SIGALRM, we will kill the
# child.
#
# We cannot avoid forking, because Python will not deliver a
# signal when a C function is running. So if Spot takes too long
# to translate some formula, it would not get interrupted.
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(30)
os.waitpid(child, 0)
exit(0)
# Global options
utf8 = False