mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 10:26:28 +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.avatar import gravatar_hash
|
||||||
from zephyr.lib.bugdown import codehilite, fenced_code
|
from zephyr.lib.bugdown import codehilite, fenced_code
|
||||||
from zephyr.lib.bugdown.fenced_code import FENCE_RE
|
from zephyr.lib.bugdown.fenced_code import FENCE_RE
|
||||||
|
from zephyr.lib.timeout import timeout
|
||||||
|
|
||||||
class Gravatar(markdown.inlinepatterns.Pattern):
|
class Gravatar(markdown.inlinepatterns.Pattern):
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
@@ -179,7 +180,10 @@ def convert(md):
|
|||||||
_md_engine.reset()
|
_md_engine.reset()
|
||||||
|
|
||||||
try:
|
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:
|
except:
|
||||||
# FIXME: Do something more reasonable here!
|
# FIXME: Do something more reasonable here!
|
||||||
html = '<p>[Humbug note: Sorry, we could not understand the formatting of your message]</p>'
|
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