Skip to content

Commit abca955

Browse files
committed
Handle possible race condition in chan_track between JOIN and MODE
1 parent 241ea5f commit abca955

1 file changed

Lines changed: 48 additions & 38 deletions

File tree

plugins/chan_track.py

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,18 @@ def updateusers(bot):
205205
return "Updating all channel data"
206206

207207

208-
@hook.irc_raw('JOIN')
208+
@hook.irc_raw(['JOIN', 'MODE'], singlethread=True)
209+
def on_join_mode(chan, nick, user, host, conn, irc_command, irc_paramlist):
210+
"""
211+
Both JOIN and MODE are handled in one hook with Hook:singlethread=True
212+
to ensure they are handled in order, avoiding a possible race condition
213+
"""
214+
if irc_command == 'JOIN':
215+
return on_join(chan, nick, user, host, conn)
216+
elif irc_command == 'MODE':
217+
return on_mode(chan, irc_paramlist, conn)
218+
219+
209220
def on_join(chan, nick, user, host, conn):
210221
if chan.startswith(':'):
211222
chan = chan[1:]
@@ -220,43 +231,6 @@ def on_join(chan, nick, user, host, conn):
220231
user_chans[chan.casefold()] = memb_data
221232

222233

223-
@hook.irc_raw('PART')
224-
def on_part(chan, nick, conn):
225-
if chan.startswith(':'):
226-
chan = chan[1:]
227-
228-
channels = conn.memory["chan_data"]
229-
nick_cf = nick.casefold()
230-
if nick_cf == conn.nick.casefold():
231-
try:
232-
del channels[chan]
233-
except KeyError:
234-
pass
235-
else:
236-
chan_data = channels[chan]
237-
try:
238-
del chan_data["users"][nick_cf]
239-
except KeyError:
240-
pass
241-
242-
243-
@hook.irc_raw('KICK')
244-
def on_kick(chan, target, conn):
245-
on_part(chan, target, conn)
246-
247-
248-
@hook.irc_raw('QUIT')
249-
def on_quit(nick, conn):
250-
nick_cf = nick.casefold()
251-
users = conn.memory["users"]
252-
if nick_cf in users:
253-
user = users[nick_cf]
254-
for memb in user.get("channels", {}).values():
255-
chan = memb["chan"]
256-
chan["users"].pop(nick_cf)
257-
258-
259-
@hook.irc_raw('MODE')
260234
def on_mode(chan, irc_paramlist, conn):
261235
if chan.startswith(':'):
262236
chan = chan[1:]
@@ -303,6 +277,42 @@ def on_mode(chan, irc_paramlist, conn):
303277
memb["status"].remove(status)
304278

305279

280+
@hook.irc_raw('PART')
281+
def on_part(chan, nick, conn):
282+
if chan.startswith(':'):
283+
chan = chan[1:]
284+
285+
channels = conn.memory["chan_data"]
286+
nick_cf = nick.casefold()
287+
if nick_cf == conn.nick.casefold():
288+
try:
289+
del channels[chan]
290+
except KeyError:
291+
pass
292+
else:
293+
chan_data = channels[chan]
294+
try:
295+
del chan_data["users"][nick_cf]
296+
except KeyError:
297+
pass
298+
299+
300+
@hook.irc_raw('KICK')
301+
def on_kick(chan, target, conn):
302+
on_part(chan, target, conn)
303+
304+
305+
@hook.irc_raw('QUIT')
306+
def on_quit(nick, conn):
307+
nick_cf = nick.casefold()
308+
users = conn.memory["users"]
309+
if nick_cf in users:
310+
user = users[nick_cf]
311+
for memb in user.get("channels", {}).values():
312+
chan = memb["chan"]
313+
chan["users"].pop(nick_cf)
314+
315+
306316
@hook.irc_raw('NICK')
307317
def on_nick(nick, irc_paramlist, conn):
308318
users = conn.memory["users"]

0 commit comments

Comments
 (0)