aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEthan Furman <ethan@stoneleaf.us>2017-01-24 12:12:06 -0800
committerEthan Furman <ethan@stoneleaf.us>2017-01-24 12:12:06 -0800
commit28cf663ff0af3ddac9a7dbe5e53e57763c532360 (patch)
tree8d0c64cf12d46e05f06fee90f95aff64f1556758 /Lib/enum.py
parentIssue #29083: Fixed the declaration of some public API functions. (diff)
downloadcpython-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.py15
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 = []