[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Fix ExitPolicy thread safety bug
commit 87cea952a27b024981e70efacc09253e22a7658f
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Wed May 8 11:05:15 2019 -0700
Fix ExitPolicy thread safety bug
Interesting catch from juga! I don't have a repro for the stacktrace they cite,
but the only way our input_rules could potentially be None is if two threads
attempt to parse the input_rules at the same time.
Creating a local reference for the input_rules to avoid this while remaining
lock-free...
https://trac.torproject.org/projects/tor/ticket/29899
---
docs/change_log.rst | 1 +
stem/exit_policy.py | 13 +++++++++----
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index 44153d55..cdb9e450 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -51,6 +51,7 @@ The following are only available within Stem's `git repository
* Added :func:`~stem.control.Controller.get_uptime` method to the :class:`~stem.control.Controller`
* Controller events could fail to be delivered in a timely fashion (:trac:`27173`)
* Adjusted :func:`~stem.control.Controller.get_microdescriptors` fallback to also use '.new' cache files (:trac:`28508`)
+ * ExitPolicies could raise TypeError when read concurrently (:trac:`29899`)
* **DORMANT** and **ACTIVE** :data:`~stem.Signal` (:spec:`4421149`)
* **Descriptors**
diff --git a/stem/exit_policy.py b/stem/exit_policy.py
index f02ec146..5bdadf9b 100644
--- a/stem/exit_policy.py
+++ b/stem/exit_policy.py
@@ -452,14 +452,19 @@ class ExitPolicy(object):
return ExitPolicy(*[rule for rule in self._get_rules() if not rule.is_default()])
def _get_rules(self):
- if self._rules is None:
+ # Local reference to our input_rules so this can be lock free. Otherwise
+ # another thread might unset our input_rules while processing them.
+
+ input_rules = self._input_rules
+
+ if self._rules is None and input_rules is not None:
rules = []
is_all_accept, is_all_reject = True, True
- if isinstance(self._input_rules, bytes):
- decompressed_rules = zlib.decompress(self._input_rules).split(b',')
+ if isinstance(input_rules, bytes):
+ decompressed_rules = zlib.decompress(input_rules).split(b',')
else:
- decompressed_rules = self._input_rules
+ decompressed_rules = input_rules
for rule in decompressed_rules:
if isinstance(rule, bytes):
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits