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 | 28cf663ff0af3ddac9a7dbe5e53e57763c532360 (patch) | |
tree | 8d0c64cf12d46e05f06fee90f95aff64f1556758 /Lib/enum.py | |
parent | Issue #29083: Fixed the declaration of some public API functions. (diff) | |
download | cpython-28cf663ff0af3ddac9a7dbe5e53e57763c532360.tar.gz cpython-28cf663ff0af3ddac9a7dbe5e53e57763c532360.tar.bz2 cpython-28cf663ff0af3ddac9a7dbe5e53e57763c532360.zip |
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 e79b0382eb0..056400d04c9 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 = [] |