]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: guard connection._pipeline using the connection lock
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 26 Mar 2022 18:02:32 +0000 (19:02 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 2 Apr 2022 23:17:57 +0000 (01:17 +0200)
psycopg/psycopg/connection.py
psycopg/psycopg/connection_async.py

index 6c09c17223a4b8199ad5fa5e28cbc7b79008fead..1a0b9393aa57490413766d42e87513537b941b9b 100644 (file)
@@ -870,12 +870,20 @@ class Connection(BaseConnection[Row]):
     @contextmanager
     def pipeline(self) -> Iterator[None]:
         """Context manager to switch the connection into pipeline mode."""
-        if self._pipeline is not None:
-            # calling pipeline recursively is no-op.
+        with self.lock:
+            if self._pipeline is None:
+                # We must enter pipeline mode: create a new one
+                pipeline = self._pipeline = Pipeline(self.pgconn)
+            else:
+                # we are already in pipeline mode: bail out as soon as we
+                # leave the lock block.
+                pipeline = None
+
+        if not pipeline:
+            # No-op re-entered inner pipeline block.
             yield
             return
 
-        pipeline = self._pipeline = Pipeline(self.pgconn)
         try:
             with pipeline:
                 try:
index 52709d67024e7d65f40fcccb0cf4b8c4f68f7998..2c0321bb67a49bc8b43f29e98cee83f49693dc73 100644 (file)
@@ -298,12 +298,20 @@ class AsyncConnection(BaseConnection[Row]):
     @asynccontextmanager
     async def pipeline(self) -> AsyncIterator[None]:
         """Context manager to switch the connection into pipeline mode."""
-        if self._pipeline is not None:
-            # calling pipeline recursively is no-op.
+        async with self.lock:
+            if self._pipeline is None:
+                # We must enter pipeline mode: create a new one
+                pipeline = self._pipeline = AsyncPipeline(self.pgconn)
+            else:
+                # we are already in pipeline mode: bail out as soon as we
+                # leave the lock block.
+                pipeline = None
+
+        if not pipeline:
+            # No-op re-entered inner pipeline block.
             yield
             return
 
-        pipeline = self._pipeline = AsyncPipeline(self.pgconn)
         try:
             async with pipeline:
                 try: