From d4154c5ce2de70d70fd8cc214e5dab71e716ae57 Mon Sep 17 00:00:00 2001 From: Conatum Date: Sat, 8 Jul 2023 09:30:10 +0300 Subject: [PATCH] fix (schedule): Fix potential deadlock. --- src/modules/schedule/cog.py | 15 +++++++++++---- src/modules/schedule/core/timeslot.py | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/modules/schedule/cog.py b/src/modules/schedule/cog.py index 2adedb6b..f4196c10 100644 --- a/src/modules/schedule/cog.py +++ b/src/modules/schedule/cog.py @@ -203,11 +203,15 @@ class ScheduleCog(LionCog): Tuple of (slotid, guildid, userid) """ slotids = set(bookingid[0] for bookingid in bookingids) - locks = [self.slotlock(slotid) for slotid in slotids] + logger.debug( + "Cancelling bookings: " + ', '.join(map(str, bookingids)) + ) # Request all relevant slotlocks - await asyncio.gather(*(lock.acquire() for lock in locks)) + locks = [self.slotlock(slotid) for slotid in sorted(slotids)] + try: + [await lock.acquire() for lock in locks] # TODO: Some benchmarking here # Should we do the channel updates in bulk? for bookingid in bookingids: @@ -231,6 +235,9 @@ class ScheduleCog(LionCog): finally: for lock in locks: lock.release() + logger.info( + "Cancelled Scheduled Session bookings: " + ', '.join(map(str, bookingids)) + ) return records async def _cancel_booking_active(self, slotid, guildid, userid): @@ -404,9 +411,9 @@ class ScheduleCog(LionCog): f"for slotids: {', '.join(map(str, slotids))}" ) t = self.bot.translator.t - locks = [self.slotlock(slotid) for slotid in slotids] - await asyncio.gather(*(lock.acquire() for lock in locks)) + locks = [self.slotlock(slotid) for slotid in sorted(slotids)] try: + [await lock.acquire() for lock in locks] # Validate bookings guild_data = await self.data.ScheduleGuild.fetch_or_create(guildid) config = ScheduleConfig(guildid, guild_data) diff --git a/src/modules/schedule/core/timeslot.py b/src/modules/schedule/core/timeslot.py index 5a0b5a70..f2849c34 100644 --- a/src/modules/schedule/core/timeslot.py +++ b/src/modules/schedule/core/timeslot.py @@ -178,6 +178,7 @@ class TimeSlot: now = utc_now() tracker = self.bot.get_cog('VoiceTrackerCog') tracking_lock = tracker.tracking_lock + sessions.sort(key=lambda s: s.guildid) session_locks = [session.lock for session in sessions] # Take the tracking lock so that sessions are not started/finished while we reset the clock