diff --git a/libmproxy/script.py b/libmproxy/script.py index 46edb86b7..6167ae053 100644 --- a/libmproxy/script.py +++ b/libmproxy/script.py @@ -128,15 +128,17 @@ class Script: class ReplyProxy(object): - def __init__(self, original_reply): - self._ignore_calls = 1 - self.lock = threading.Lock() + def __init__(self, original_reply, script_thread): self.original_reply = original_reply + self.script_thread = script_thread + self._ignore_call = True + self.lock = threading.Lock() def __call__(self, *args, **kwargs): with self.lock: - if self._ignore_calls > 0: - self._ignore_calls -= 1 + if self._ignore_call: + self.script_thread.start() + self._ignore_call = False return self.original_reply(*args, **kwargs) @@ -145,16 +147,19 @@ class ReplyProxy(object): def _handle_concurrent_reply(fn, o, *args, **kwargs): - # Make first call to o.reply a no op - - reply_proxy = ReplyProxy(o.reply) - o.reply = reply_proxy + # Make first call to o.reply a no op and start the script thread. + # We must not start the script thread before, as this may lead to a nasty race condition + # where the script thread replies a different response before the normal reply, which then gets swallowed. def run(): fn(*args, **kwargs) # If the script did not call .reply(), we have to do it now. reply_proxy() - ScriptThread(target=run).start() + + script_thread = ScriptThread(target=run) + + reply_proxy = ReplyProxy(o.reply, script_thread) + o.reply = reply_proxy class ScriptThread(threading.Thread):