From 0eaff9d193c650035d49e97ecd55c0a33a3aa4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Sun, 24 Jan 2016 21:09:39 +0100 Subject: [PATCH] Fix race-condition that resulted in the REPL hanging With two successive requests, for example a completion request and an eval request fired from two different Python threads, the second response could end up overwriting the first one before it got processed. The initial design assumed that only a single Python thread would be making these requests, but that changed when the completion was introduced. We now fix this issue by using a queue and knowing that these requests are processed and replied to in FIFO order. --- src/frida/repl.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/frida/repl.py b/src/frida/repl.py index 3ba86cb..b1ebd3d 100644 --- a/src/frida/repl.py +++ b/src/frida/repl.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals, print_function def main(): import codecs + from collections import deque from colorama import Fore, Style import frida from frida.application import ConsoleApplication @@ -24,7 +25,7 @@ def main(): self._seqno = 0 self._ready = threading.Event() self._response_cond = threading.Condition() - self._response_data = None + self._response_queue = deque() self._completor_locals = [] self._history = FileHistory(os.path.join(os.path.expanduser('~'), '.frida_history')) self._completer = FridaCompleter(self) @@ -313,12 +314,11 @@ def main(): def _evaluate(self, text): self._reactor.schedule(lambda: self._script.post_message({'name': '.evaluate', 'payload': {'expression': text}})) with self._response_cond: - while self._response_data is None: + while len(self._response_queue) == 0: if not self._reactor.is_running(): raise frida.InvalidOperationError("Invalid operation while stopping") self._response_cond.wait(0.5) - response = self._response_data - self._response_data = None + response = self._response_queue.popleft() stanza, data = response if data is not None: return ('binary', data) @@ -334,7 +334,8 @@ def main(): if message_type == 'send': stanza = message['payload'] with self._response_cond: - self._response_data = (stanza, data) + response = (stanza, data) + self._response_queue.append(response) self._response_cond.notify() elif message_type == 'error': text = message.get('stack', message['description'])