Fix waiter cancellation in asyncio.Lock (#1031) (#2037)

Avoid a deadlock when the waiter who is about to take the lock is
cancelled

Issue #27585
diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py
index deefc93..9266183 100644
--- a/Lib/asyncio/locks.py
+++ b/Lib/asyncio/locks.py
@@ -176,6 +176,10 @@
             yield from fut
             self._locked = True
             return True
+        except futures.CancelledError:
+            if not self._locked:
+                self._wake_up_first()
+            raise
         finally:
             self._waiters.remove(fut)
 
@@ -192,14 +196,17 @@
         """
         if self._locked:
             self._locked = False
-            # Wake up the first waiter who isn't cancelled.
-            for fut in self._waiters:
-                if not fut.done():
-                    fut.set_result(True)
-                    break
+            self._wake_up_first()
         else:
             raise RuntimeError('Lock is not acquired.')
 
+    def _wake_up_first(self):
+        """Wake up the first waiter who isn't cancelled."""
+        for fut in self._waiters:
+            if not fut.done():
+                fut.set_result(True)
+                break
+
 
 class Event:
     """Asynchronous equivalent to threading.Event.