Sourcing python-remove-tests-dir-hook Sourcing python-catch-conflicts-hook.sh Sourcing python-remove-bin-bytecode-hook.sh Sourcing pypa-build-hook Using pypaBuildPhase Sourcing python-runtime-deps-check-hook Using pythonRuntimeDepsCheckHook Sourcing pypa-install-hook Using pypaInstallPhase Sourcing python-imports-check-hook.sh Using pythonImportsCheckPhase Sourcing python-namespaces-hook Sourcing python-catch-conflicts-hook.sh Sourcing pytest-check-hook Using pytestCheckPhase Running phase: unpackPhase unpacking source archive /nix/store/054lh8j4xjg0y5qsavbgn5jqsrg561sl-nixbot source root is nixbot setting SOURCE_DATE_EPOCH to timestamp 315619200 of file "nixbot/pyproject.toml" Running phase: patchPhase Running phase: updateAutotoolsGnuConfigScriptsPhase Running phase: configurePhase no configure script, doing nothing Running phase: buildPhase Executing pypaBuildPhase Creating a wheel... pypa build flags: --no-isolation --outdir dist/ --wheel * Getting build dependencies for wheel... * Building wheel... Successfully built nixbot-0.0.1-py3-none-any.whl Finished creating a wheel... Finished executing pypaBuildPhase Running phase: pythonRuntimeDepsCheckHook Executing pythonRuntimeDepsCheck Checking runtime dependencies for nixbot-0.0.1-py3-none-any.whl Finished executing pythonRuntimeDepsCheck Running phase: installPhase Executing pypaInstallPhase Successfully installed nixbot-0.0.1-py3-none-any.whl Finished executing pypaInstallPhase Running phase: pythonOutputDistPhase Executing pythonOutputDistPhase Finished executing pythonOutputDistPhase Running phase: fixupPhase checking for references to /nix/var/nix/builds/nix-54604-2818304180/ in /nix/store/cl46r9ryf6cqna6cv3qwpd5plsdg7jww-python3.14-nixbot-tests... patching script interpreter paths in /nix/store/cl46r9ryf6cqna6cv3qwpd5plsdg7jww-python3.14-nixbot-tests stripping (with command strip and flags -S) in /nix/store/cl46r9ryf6cqna6cv3qwpd5plsdg7jww-python3.14-nixbot-tests/lib /nix/store/cl46r9ryf6cqna6cv3qwpd5plsdg7jww-python3.14-nixbot-tests/bin checking for references to /nix/var/nix/builds/nix-54604-2818304180/ in /nix/store/klwzfbbb4w6p1xanpzyh7ylayc4p2yqj-python3.14-nixbot-tests-dist... patching script interpreter paths in /nix/store/klwzfbbb4w6p1xanpzyh7ylayc4p2yqj-python3.14-nixbot-tests-dist Rewriting #!/nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/bin/python3.14 to #!/nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6 wrapping `/nix/store/cl46r9ryf6cqna6cv3qwpd5plsdg7jww-python3.14-nixbot-tests/bin/nixbot'... Executing pythonRemoveTestsDir Finished executing pythonRemoveTestsDir Running phase: installCheckPhase no Makefile or custom installCheckPhase, doing nothing Running phase: pythonCatchConflictsPhase Running phase: pythonRemoveBinBytecodePhase Running phase: pythonImportsCheckPhase Executing pythonImportsCheckPhase Running phase: pytestCheckPhase Executing pytestCheckPhase pytest flags: -m pytest --numprocesses=10 /nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ============================= test session starts ============================== platform darwin -- Python 3.14.6, pytest-9.1.1, pluggy-1.6.0 benchmark: 5.2.3 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000) rootdir: /nix/var/nix/builds/nix-54604-2818304180/nixbot configfile: pyproject.toml plugins: asyncio-1.4.0, timeout-2.4.0, xdist-3.8.0, benchmark-5.2.3, anyio-4.14.2 asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function timeout: 60.0s timeout method: signal timeout func_only: False initialized: 10/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) /nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ready: 2/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) /nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ready: 4/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) /nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ready: 6/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ready: 7/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) ready: 8/10 workers/nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) /nix/store/kfbmrm2rads9m3za8am89kll1xmzlbra-python3.14-pytest-benchmark-5.2.3/lib/python3.14/site-packages/pytest_benchmark/logger.py:44: PytestBenchmarkWarning: Benchmarks are automatically disabled because xdist plugin is active.Benchmarks cannot be performed reliably in a parallelized environment. warner(PytestBenchmarkWarning(text)) 10 workers [860 items] ..............s.s..sss.ss.ss............................................ [ 8%] ........................................................................ [ 16%] ........................................................................ [ 25%] ......................s................................................. [ 33%] ........................................................................ [ 41%] ................................s....................................... [ 50%] ...................................ssssssssssss......................... [ 58%] .....................................................................s.. [ 66%] ..............................F......................................... [ 75%] ............................................ssss........................ [ 83%] ................s....................................................... [ 92%] .................................................................... [100%] =================================== FAILURES =================================== ________________ test_executor_hard_cancel_kills_process_group _________________ [gw3] darwin -- Python 3.14.6 /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/bin/python3.14 self = cmd = ['nix', 'build', '--log-format', 'internal-json', '--option', 'keep-going', ...] env = None job = NixEvalJobSuccess(attr='foo', attr_path=['foo'], cache_status=, needed_builds=['/ni...o', warnings=[], traces=[], stats=None, outputs={'out': '/nix/store/foo-out'}, system='x86_64-linux', extra_value=None) log_writer = LogWriter(path=PosixPath('/nix/var/nix/builds/nix-54604-2818304180/pytest-of-_nixbld14/pytest-0/popen-gw3/test_executo...ard.backend_c.ZstdCompressor object at 0x10e865b60>, _flush_lock=) cwd = PosixPath('/nix/var/nix/builds/nix-54604-2818304180/pytest-of-_nixbld14/pytest-0/popen-gw3/test_executor_hard_cancel_kill0') cancel_event = on_built = None async def _run_nix( # noqa: PLR0913 self, cmd: list[str], env: dict[str, str] | None, job: NixEvalJobSuccess, log_writer: LogWriter, cwd: Path, cancel_event: asyncio.Event, on_built: Callable[[str], None] | None, ) -> tuple[BuildOutcome, bool]: group = await ProcessGroup.start( cmd, cwd=cwd, env=env, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, limit=STREAM_LIMIT, ) proc = group.proc assert proc.stdout is not None # noqa: S101 output_tail: deque[bytes] = deque(maxlen=100) capture = StructuredCapture(on_built=on_built) log_writer.capture = capture pump_task = asyncio.create_task( _pump_output(proc.stdout, output_tail, log_writer, capture) ) cancel_task = asyncio.create_task(cancel_event.wait()) try: wait_task = asyncio.ensure_future(proc.wait()) > done, _ = await asyncio.wait( {wait_task, cancel_task}, timeout=self.settings.timeout, return_when=asyncio.FIRST_COMPLETED, ) nixbot/executor.py:938: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/tasks.py:432: in wait return await _wait(fs, timeout, return_when, loop) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ fs = {>} timeout = 10800, return_when = 'FIRST_COMPLETED' loop = <_UnixSelectorEventLoop running=False closed=False debug=False> async def _wait(fs, timeout, return_when, loop): """Internal helper for wait(). The fs argument must be a collection of Futures. """ assert fs, 'Set of Futures is empty.' waiter = loop.create_future() timeout_handle = None if timeout is not None: timeout_handle = loop.call_later(timeout, _release_waiter, waiter) counter = len(fs) cur_task = current_task() def _on_completion(f): nonlocal counter counter -= 1 if (counter <= 0 or return_when == FIRST_COMPLETED or return_when == FIRST_EXCEPTION and (not f.cancelled() and f.exception() is not None)): if timeout_handle is not None: timeout_handle.cancel() if not waiter.done(): waiter.set_result(None) futures.future_discard_from_awaited_by(f, cur_task) for f in fs: f.add_done_callback(_on_completion) futures.future_add_to_awaited_by(f, cur_task) try: > await waiter E asyncio.exceptions.CancelledError /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/tasks.py:521: CancelledError During handling of the above exception, another exception occurred: fut = > timeout = 5 async def wait_for(fut, timeout): """Wait for the single Future or coroutine to complete, with timeout. Coroutine will be wrapped in Task. Returns result of the Future or coroutine. When a timeout occurs, it cancels the task and raises TimeoutError. To avoid the task cancellation, wrap it in shield(). If the wait is cancelled, the task is also cancelled. If the task suppresses the cancellation and returns a value instead, that value is returned. This function is a coroutine. """ # The special case for timeout <= 0 is for the following case: # # async def test_waitfor(): # func_started = False # # async def func(): # nonlocal func_started # func_started = True # # try: # await asyncio.wait_for(func(), 0) # except asyncio.TimeoutError: # assert not func_started # else: # assert False # # asyncio.run(test_waitfor()) if timeout is not None and timeout <= 0: fut = ensure_future(fut) if fut.done(): return fut.result() await _cancel_and_wait(fut) try: return fut.result() except exceptions.CancelledError as exc: raise TimeoutError from exc async with timeouts.timeout(timeout): > return await fut ^^^^^^^^^ /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/tasks.py:488: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ nixbot/executor.py:855: in build_attribute outcome, transient = await self._run_once( nixbot/executor.py:903: in _run_once return await self._run_nix( nixbot/executor.py:983: in _run_nix await group.reap() /nix/store/rxaa7anm1s3bzvhl9b9hl11xx3haq9y5-python3.14-nixbot-effects/lib/python3.14/site-packages/nixbot_effects/proc.py:82: in reap await self.proc.wait() /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/subprocess.py:137: in wait return await self._transport._wait() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_UnixSubprocessTransport pid=57782 returncode=-9 stdout=<_UnixReadPipeTransport fd=16 polling>> async def _wait(self): """Wait until the process exit and return the process return code. This method is a coroutine.""" if self._returncode is not None: return self._returncode waiter = self._loop.create_future() self._exit_waiters.append(waiter) > return await waiter ^^^^^^^^^^^^ E asyncio.exceptions.CancelledError /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/base_subprocess.py:255: CancelledError The above exception was the direct cause of the following exception: tmp_path = PosixPath('/nix/var/nix/builds/nix-54604-2818304180/pytest-of-_nixbld14/pytest-0/popen-gw3/test_executor_hard_cancel_kill0') fake_nix = PosixPath('/nix/var/nix/builds/nix-54604-2818304180/pytest-of-_nixbld14/pytest-0/popen-gw3/test_executor_hard_cancel_kill0/control') async def test_executor_hard_cancel_kills_process_group( tmp_path: Path, fake_nix: Path ) -> None: """Cancelling the build task itself (not via the cancel event) must not leak the running nix process group. Group-kill semantics themselves are covered by test_proc.test_reap_kills_whole_group. This checks the executor's hard-cancel wiring (the finally path that also stops the log pump). """ fake_nix.write_text("hangpid") pidfile = tmp_path / "pid" executor = NixBuildExecutor(FairScheduler(2), BuildSettings(log_dir=tmp_path)) writer = LogWriter(path=tmp_path / "log.zst") task = asyncio.create_task( executor.build_attribute("b", mk_job(), writer, tmp_path) ) while ( # noqa: ASYNC110 — polling an external file is the point not pidfile.exists() or not pidfile.read_text().strip() ): await asyncio.sleep(0.01) task.cancel() with contextlib.suppress(asyncio.CancelledError): > await asyncio.wait_for(task, timeout=5) nixbot/tests/test_executor.py:430: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/tasks.py:487: in wait_for async with timeouts.timeout(timeout): ^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_type = exc_val = CancelledError(), exc_tb = async def __aexit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, ) -> bool | None: assert self._state in (_State.ENTERED, _State.EXPIRING) if self._timeout_handler is not None: self._timeout_handler.cancel() self._timeout_handler = None if self._state is _State.EXPIRING: self._state = _State.EXPIRED if self._task.uncancel() <= self._cancelling and exc_type is not None: # Since there are no new cancel requests, we're # handling this. if issubclass(exc_type, exceptions.CancelledError): > raise TimeoutError from exc_val E TimeoutError /nix/store/i9q7np6h9bwa3ps6937lpwarkqw0izbf-python3-3.14.6/lib/python3.14/asyncio/timeouts.py:115: TimeoutError =========================== short test summary info ============================ FAILED nixbot/tests/test_executor.py::test_executor_hard_cancel_kills_process_group - TimeoutError ============= 1 failed, 830 passed, 29 skipped in 78.40s (0:01:18) =============