Skip to content

Commit 66a4d6b

Browse files
authored
AsyncIO Race Condition Fix (#2641)
1 parent 318b114 commit 66a4d6b

File tree

7 files changed

+764
-6
lines changed

7 files changed

+764
-6
lines changed

redis/asyncio/client.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,16 @@ async def execute(self, raise_on_error: bool = True):
13851385
conn = cast(Connection, conn)
13861386

13871387
try:
1388-
return await conn.retry.call_with_retry(
1389-
lambda: execute(conn, stack, raise_on_error),
1390-
lambda error: self._disconnect_raise_reset(conn, error),
1388+
return await asyncio.shield(
1389+
conn.retry.call_with_retry(
1390+
lambda: execute(conn, stack, raise_on_error),
1391+
lambda error: self._disconnect_raise_reset(conn, error),
1392+
)
13911393
)
1394+
except asyncio.CancelledError:
1395+
# not supposed to be possible, yet here we are
1396+
await conn.disconnect(nowait=True)
1397+
raise
13921398
finally:
13931399
await self.reset()
13941400

redis/asyncio/cluster.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -1002,10 +1002,18 @@ async def execute_command(self, *args: Any, **kwargs: Any) -> Any:
10021002
await connection.send_packed_command(connection.pack_command(*args), False)
10031003

10041004
# Read response
1005+
return await asyncio.shield(
1006+
self._parse_and_release(connection, args[0], **kwargs)
1007+
)
1008+
1009+
async def _parse_and_release(self, connection, *args, **kwargs):
10051010
try:
1006-
return await self.parse_response(connection, args[0], **kwargs)
1011+
return await self.parse_response(connection, *args, **kwargs)
1012+
except asyncio.CancelledError:
1013+
# should not be possible
1014+
await connection.disconnect(nowait=True)
1015+
raise
10071016
finally:
1008-
# Release connection
10091017
self._free.append(connection)
10101018

10111019
async def execute_pipeline(self, commands: List["PipelineCommand"]) -> bool:

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
long_description_content_type="text/markdown",
99
keywords=["Redis", "key-value store", "database"],
1010
license="MIT",
11-
version="4.5.2",
11+
version="4.5.3",
1212
packages=find_packages(
1313
include=[
1414
"redis",

tests/asynctests

+285
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
test_response_callbacks
2+
test_case_insensitive_command_names
3+
test_command_on_invalid_key_type
4+
test_acl_cat_no_category
5+
test_acl_cat_with_category
6+
test_acl_deluser
7+
test_acl_genpass
8+
test_acl_getuser_setuser
9+
test_acl_list
10+
test_acl_log
11+
test_acl_setuser_categories_without_prefix_fails
12+
test_acl_setuser_commands_without_prefix_fails
13+
test_acl_setuser_add_passwords_and_nopass_fails
14+
test_acl_users
15+
test_acl_whoami
16+
test_client_list
17+
test_client_list_type
18+
test_client_id
19+
test_client_unblock
20+
test_client_getname
21+
test_client_setname
22+
test_client_kill
23+
test_client_kill_filter_invalid_params
24+
test_client_kill_filter_by_id
25+
test_client_kill_filter_by_addr
26+
test_client_list_after_client_setname
27+
test_client_pause
28+
test_config_get
29+
test_config_resetstat
30+
test_config_set
31+
test_dbsize
32+
test_echo
33+
test_info
34+
test_lastsave
35+
test_object
36+
test_ping
37+
test_slowlog_get
38+
test_slowlog_get_limit
39+
test_slowlog_length
40+
test_time
41+
test_never_decode_option
42+
test_empty_response_option
43+
test_append
44+
test_bitcount
45+
test_bitop_not_empty_string
46+
test_bitop_not
47+
test_bitop_not_in_place
48+
test_bitop_single_string
49+
test_bitop_string_operands
50+
test_bitpos
51+
test_bitpos_wrong_arguments
52+
test_decr
53+
test_decrby
54+
test_delete
55+
test_delete_with_multiple_keys
56+
test_delitem
57+
test_unlink
58+
test_unlink_with_multiple_keys
59+
test_dump_and_restore
60+
test_dump_and_restore_and_replace
61+
test_dump_and_restore_absttl
62+
test_exists
63+
test_exists_contains
64+
test_expire
65+
test_expireat_datetime
66+
test_expireat_no_key
67+
test_expireat_unixtime
68+
test_get_and_set
69+
test_get_set_bit
70+
test_getrange
71+
test_getset
72+
test_incr
73+
test_incrby
74+
test_incrbyfloat
75+
test_keys
76+
test_mget
77+
test_mset
78+
test_msetnx
79+
test_pexpire
80+
test_pexpireat_datetime
81+
test_pexpireat_no_key
82+
test_pexpireat_unixtime
83+
test_psetex
84+
test_psetex_timedelta
85+
test_pttl
86+
test_pttl_no_key
87+
test_randomkey
88+
test_rename
89+
test_renamenx
90+
test_set_nx
91+
test_set_xx
92+
test_set_px
93+
test_set_px_timedelta
94+
test_set_ex
95+
test_set_ex_timedelta
96+
test_set_multipleoptions
97+
test_set_keepttl
98+
test_setex
99+
test_setnx
100+
test_setrange
101+
test_strlen
102+
test_substr
103+
test_ttl
104+
test_ttl_nokey
105+
test_type
106+
test_blpop
107+
test_brpop
108+
test_brpoplpush
109+
test_brpoplpush_empty_string
110+
test_lindex
111+
test_linsert
112+
test_llen
113+
test_lpop
114+
test_lpush
115+
test_lpushx
116+
test_lrange
117+
test_lrem
118+
test_lset
119+
test_ltrim
120+
test_rpop
121+
test_rpoplpush
122+
test_rpush
123+
test_lpos
124+
test_rpushx
125+
test_scan
126+
test_scan_type
127+
test_scan_iter
128+
test_sscan
129+
test_sscan_iter
130+
test_hscan
131+
test_hscan_iter
132+
test_zscan
133+
test_zscan_iter
134+
test_sadd
135+
test_scard
136+
test_sdiff
137+
test_sdiffstore
138+
test_sinter
139+
test_sinterstore
140+
test_sismember
141+
test_smembers
142+
test_smove
143+
test_spop
144+
test_spop_multi_value
145+
test_srandmember
146+
test_srandmember_multi_value
147+
test_srem
148+
test_sunion
149+
test_sunionstore
150+
test_zadd
151+
test_zadd_nx
152+
test_zadd_xx
153+
test_zadd_ch
154+
test_zadd_incr
155+
test_zadd_incr_with_xx
156+
test_zcard
157+
test_zcount
158+
test_zincrby
159+
test_zlexcount
160+
test_zinterstore_sum
161+
test_zinterstore_max
162+
test_zinterstore_min
163+
test_zinterstore_with_weight
164+
test_zpopmax
165+
test_zpopmin
166+
test_bzpopmax
167+
test_bzpopmin
168+
test_zrange
169+
test_zrangebylex
170+
test_zrevrangebylex
171+
test_zrangebyscore
172+
test_zrank
173+
test_zrem
174+
test_zrem_multiple_keys
175+
test_zremrangebylex
176+
test_zremrangebyrank
177+
test_zremrangebyscore
178+
test_zrevrange
179+
test_zrevrangebyscore
180+
test_zrevrank
181+
test_zscore
182+
test_zunionstore_sum
183+
test_zunionstore_max
184+
test_zunionstore_min
185+
test_zunionstore_with_weight
186+
test_pfadd
187+
test_pfcount
188+
test_pfmerge
189+
test_hget_and_hset
190+
test_hset_with_multi_key_values
191+
test_hset_without_data
192+
test_hdel
193+
test_hexists
194+
test_hgetall
195+
test_hincrby
196+
test_hincrbyfloat
197+
test_hkeys
198+
test_hlen
199+
test_hmget
200+
test_hmset
201+
test_hsetnx
202+
test_hvals
203+
test_hstrlen
204+
test_sort_basic
205+
test_sort_limited
206+
test_sort_by
207+
test_sort_get
208+
test_sort_get_multi
209+
test_sort_get_groups_two
210+
test_sort_groups_string_get
211+
test_sort_groups_just_one_get
212+
test_sort_groups_no_get
213+
test_sort_groups_three_gets
214+
test_sort_desc
215+
test_sort_alpha
216+
test_sort_store
217+
test_sort_all_options
218+
test_sort_issue_924
219+
test_cluster_addslots
220+
test_cluster_count_failure_reports
221+
test_cluster_countkeysinslot
222+
test_cluster_delslots
223+
test_cluster_failover
224+
test_cluster_forget
225+
test_cluster_info
226+
test_cluster_keyslot
227+
test_cluster_meet
228+
test_cluster_nodes
229+
test_cluster_replicate
230+
test_cluster_reset
231+
test_cluster_saveconfig
232+
test_cluster_setslot
233+
test_cluster_slaves
234+
test_readwrite
235+
test_readonly_invalid_cluster_state
236+
test_readonly
237+
test_geoadd
238+
test_geoadd_invalid_params
239+
test_geodist
240+
test_geodist_units
241+
test_geodist_missing_one_member
242+
test_geodist_invalid_units
243+
test_geohash
244+
test_geopos
245+
test_geopos_no_value
246+
test_old_geopos_no_value
247+
test_georadius
248+
test_georadius_no_values
249+
test_georadius_units
250+
test_georadius_with
251+
test_georadius_count
252+
test_georadius_sort
253+
test_georadius_store
254+
test_georadius_store_dist
255+
test_georadiusmember
256+
test_xack
257+
test_xadd
258+
test_xclaim
259+
test_xclaim_trimmed
260+
test_xdel
261+
test_xgroup_create
262+
test_xgroup_create_mkstream
263+
test_xgroup_delconsumer
264+
test_xgroup_destroy
265+
test_xgroup_setid
266+
test_xinfo_consumers
267+
test_xinfo_stream
268+
test_xlen
269+
test_xpending
270+
test_xpending_range
271+
test_xrange
272+
test_xread
273+
test_xreadgroup
274+
test_xrevrange
275+
test_xtrim
276+
test_bitfield_operations
277+
test_bitfield_ro
278+
test_memory_stats
279+
test_memory_usage
280+
test_module_list
281+
test_binary_get_set
282+
test_binary_lists
283+
test_22_info
284+
test_large_responses
285+
test_floating_point_encoding

0 commit comments

Comments
 (0)