mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 18:36:36 +00:00
bugdown: Spend at most 5 seconds rendering a message
(imported from commit bc092acc8b2b9f8a63af669de06c6f7512ccf8c9)
This commit is contained in:
@@ -7,6 +7,7 @@ import re
|
||||
from zephyr.lib.avatar import gravatar_hash
|
||||
from zephyr.lib.bugdown import codehilite, fenced_code
|
||||
from zephyr.lib.bugdown.fenced_code import FENCE_RE
|
||||
from zephyr.lib.timeout import timeout
|
||||
|
||||
class Gravatar(markdown.inlinepatterns.Pattern):
|
||||
def handleMatch(self, match):
|
||||
@@ -179,7 +180,10 @@ def convert(md):
|
||||
_md_engine.reset()
|
||||
|
||||
try:
|
||||
html = _md_engine.convert(md)
|
||||
# Spend at most 5 seconds rendering.
|
||||
# Sometimes Python-Markdown is really slow; see
|
||||
# https://trac.humbughq.com/ticket/345
|
||||
html = timeout(5, _md_engine.convert, md)
|
||||
except:
|
||||
# FIXME: Do something more reasonable here!
|
||||
html = '<p>[Humbug note: Sorry, we could not understand the formatting of your message]</p>'
|
||||
|
||||
45
zephyr/lib/timeout.py
Normal file
45
zephyr/lib/timeout.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import threading
|
||||
|
||||
# Based on http://code.activestate.com/recipes/483752/
|
||||
|
||||
class TimeoutExpired(Exception):
|
||||
'''Exception raised when a function times out.'''
|
||||
def __str__(self):
|
||||
return 'Function call timed out.'
|
||||
|
||||
def timeout(timeout, func, *args, **kwargs):
|
||||
'''Call the function in a separate thread.
|
||||
Return its return value, or raise an exception,
|
||||
within 'timeout' seconds.
|
||||
|
||||
The function may still be running in the background!
|
||||
|
||||
This may also fail to interrupt functions which are
|
||||
stuck in a long-running primitive interpreter
|
||||
operation.'''
|
||||
|
||||
class TimeoutThread(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.result = None
|
||||
self.exn = None
|
||||
|
||||
# Don't block the whole program from exiting
|
||||
# if this is the only thread left.
|
||||
self.daemon = True
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.result = func(*args, **kwargs)
|
||||
except BaseException, e:
|
||||
self.exn = e
|
||||
|
||||
thread = TimeoutThread()
|
||||
thread.start()
|
||||
thread.join(timeout)
|
||||
|
||||
if thread.isAlive():
|
||||
raise TimeoutExpired
|
||||
if thread.exn:
|
||||
raise thread.exn
|
||||
return thread.result
|
||||
Reference in New Issue
Block a user