diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2017-01-24 12:12:06 -0800 |
---|---|---|
committer | Ethan Furman <ethan@stoneleaf.us> | 2017-01-24 12:12:06 -0800 |
commit | d3b94b2105b09a8d6b49a297bc6cd4b3dcef3467 (patch) | |
tree | 019991ad9afce991b068a807156cae93c912e87d /Lib/enum.py | |
parent | f7504c0ffb2450a20dba1f77f8e784d6c5f7200a (diff) | |
download | cpython-d3b94b2105b09a8d6b49a297bc6cd4b3dcef3467.tar.gz |
closes issue29167: fix race condition in (Int)Flag
Diffstat (limited to 'Lib/enum.py')
-rw-r--r-- | Lib/enum.py | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/Lib/enum.py b/Lib/enum.py index e79b0382eb..056400d04c 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -690,7 +690,9 @@ class Flag(Enum): pseudo_member = object.__new__(cls) pseudo_member._name_ = None pseudo_member._value_ = value - cls._value2member_map_[value] = pseudo_member + # use setdefault in case another thread already created a composite + # with this value + pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) return pseudo_member def __contains__(self, other): @@ -785,7 +787,9 @@ class IntFlag(int, Flag): pseudo_member = int.__new__(cls, value) pseudo_member._name_ = None pseudo_member._value_ = value - cls._value2member_map_[value] = pseudo_member + # use setdefault in case another thread already created a composite + # with this value + pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) return pseudo_member def __or__(self, other): @@ -835,18 +839,21 @@ def _decompose(flag, value): # _decompose is only called if the value is not named not_covered = value negative = value < 0 + # issue29167: wrap accesses to _value2member_map_ in a list to avoid race + # conditions between iterating over it and having more psuedo- + # members added to it if negative: # only check for named flags flags_to_check = [ (m, v) - for v, m in flag._value2member_map_.items() + for v, m in list(flag._value2member_map_.items()) if m.name is not None ] else: # check for named flags and powers-of-two flags flags_to_check = [ (m, v) - for v, m in flag._value2member_map_.items() + for v, m in list(flag._value2member_map_.items()) if m.name is not None or _power_of_two(v) ] members = [] |