diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 98e72f212aa203..0423bc100b2d93 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -22,7 +22,7 @@ def __init__(self, loop, protocol, args, shell, self._proc = None self._pid = None self._returncode = None - self._exit_waiters = [] + self._exit_waiters = set() self._pending_calls = collections.deque() self._pipes = {} self._finished = False @@ -211,6 +211,14 @@ async def _connect_pipes(self, waiter): except (SystemExit, KeyboardInterrupt): raise except BaseException as exc: + # Close any pipes that were already connected before the + # error/cancellation to avoid leaking file descriptors. + for proto in self._pipes.values(): + if proto is not None: + proto.pipe.close() + for raw_pipe in (proc.stdin, proc.stdout, proc.stderr): + if raw_pipe is not None: + raw_pipe.close() if waiter is not None and not waiter.cancelled(): waiter.set_exception(exc) else: @@ -260,8 +268,12 @@ async def _wait(self): return self._returncode waiter = self._loop.create_future() - self._exit_waiters.append(waiter) - return await waiter + self._exit_waiters.add(waiter) + try: + return await waiter + finally: + if self._exit_waiters is not None: + self._exit_waiters.discard(waiter) def _try_finish(self): assert not self._finished diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index d436512d6c45fc..1a7d534261ed72 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -213,7 +213,7 @@ async def _make_subprocess_transport(self, protocol, args, shell, raise except BaseException: transp.close() - await transp._wait() + await tasks.shield(transp._wait()) raise return transp diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index 8241c10b32d105..efc7c0c158d390 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -406,7 +406,7 @@ async def _make_subprocess_transport(self, protocol, args, shell, raise except BaseException: transp.close() - await transp._wait() + await tasks.shield(transp._wait()) raise return transp diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index ce127e73f50d8a..f9b4fe53acb134 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -12,7 +12,7 @@ from asyncio import subprocess from test.test_asyncio import utils as test_utils from test import support -from test.support import os_helper, warnings_helper, gc_collect +from test.support import os_helper, gc_collect if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") @@ -1028,7 +1028,6 @@ async def main(): self.loop.run_until_complete(main()) - @warnings_helper.ignore_warnings(category=ResourceWarning) def test_subprocess_read_pipe_cancelled(self): async def main(): loop = asyncio.get_running_loop() @@ -1039,7 +1038,6 @@ async def main(): asyncio.run(main()) gc_collect() - @warnings_helper.ignore_warnings(category=ResourceWarning) def test_subprocess_write_pipe_cancelled(self): async def main(): loop = asyncio.get_running_loop() @@ -1050,7 +1048,6 @@ async def main(): asyncio.run(main()) gc_collect() - @warnings_helper.ignore_warnings(category=ResourceWarning) def test_subprocess_read_write_pipe_cancelled(self): async def main(): loop = asyncio.get_running_loop() diff --git a/Misc/NEWS.d/next/Library/2026-07-21-20-34-05.gh-issue-154389.DlTiii.rst b/Misc/NEWS.d/next/Library/2026-07-21-20-34-05.gh-issue-154389.DlTiii.rst new file mode 100644 index 00000000000000..eb2e2edc2d720e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-21-20-34-05.gh-issue-154389.DlTiii.rst @@ -0,0 +1,3 @@ +Fix :func:`uuid.uuid1` on OpenBSD: +it returned a version 4 UUID, +because ``uuid_create()`` generates random UUIDs on this platform. diff --git a/configure b/configure index 71fa0b435d1650..93bc5545e9de6e 100755 --- a/configure +++ b/configure @@ -15294,9 +15294,10 @@ then : fi -# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. +# gh-124228: While the libuuid library is available on NetBSD and OpenBSD, +# it supports only UUID version 4. # This restriction inhibits the proper generation of time-based UUIDs. -if test "$ac_sys_system" = "NetBSD"; then +if test "$ac_sys_system" = "NetBSD" || test "$ac_sys_system" = "OpenBSD"; then have_uuid=missing printf "%s\n" "#define HAVE_UUID_H 0" >>confdefs.h diff --git a/configure.ac b/configure.ac index 5fcf406087cbe5..a9c706f3c23cb1 100644 --- a/configure.ac +++ b/configure.ac @@ -4070,9 +4070,10 @@ AS_VAR_IF([ac_cv_have_uuid_generate_time_safe], [yes], [ AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) -# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. +# gh-124228: While the libuuid library is available on NetBSD and OpenBSD, +# it supports only UUID version 4. # This restriction inhibits the proper generation of time-based UUIDs. -if test "$ac_sys_system" = "NetBSD"; then +if test "$ac_sys_system" = "NetBSD" || test "$ac_sys_system" = "OpenBSD"; then have_uuid=missing AC_DEFINE([HAVE_UUID_H], [0]) fi