Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run_process with fail_after causes RuntimeError on timeout #669

Closed
2 tasks done
jerr0328 opened this issue Jan 12, 2024 · 0 comments · Fixed by #672
Closed
2 tasks done

run_process with fail_after causes RuntimeError on timeout #669

jerr0328 opened this issue Jan 12, 2024 · 0 comments · Fixed by #672
Labels
bug Something isn't working

Comments

@jerr0328
Copy link

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

AnyIO version

4.2.0

Python version

3.12.1

What happened?

I am using fail_after to timeout if some task group is taking too long, usually due to being stuck in some subprocess call longer than expected. I was able to reproduce this in a small script (posted in the other section) which results in the following exception after hitting the timeout handler in this case.

Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x1011d8360>
Traceback (most recent call last):
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/base_subprocess.py", line 126, in __del__
    self.close()
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/base_subprocess.py", line 104, in close
    proto.pipe.close()
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/unix_events.py", line 568, in close
    self._close(None)
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/unix_events.py", line 592, in _close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/base_events.py", line 792, in call_soon
    self._check_closed()
  File "/Users/jmayeres/.pyenv/versions/3.12.1/lib/python3.12/asyncio/base_events.py", line 539, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

The expectation would be that no RuntimeError is raised. I noticed that I don't have this issue if I use open_process and handle the output via text streams, but if I use run_process like in this example I get errors when the timeout is raised. I believe there's also some other weird stuff happening with these exceptions but I wanted to keep the example simple (in our working code there's some nested task groups and it seems like we don't get the timeout exception handler reached but the exception gets absorbed somewhere).

How can we reproduce the bug?

Invoking the following in python results in an exception after printing "Timed out!". Note that I'm running this on macOS 14.2.1

from anyio import create_task_group, fail_after, run, run_process


async def subprocess_output_no_stream():
    result = await run_process("while true; do ps aux; sleep 1; done")
    stdout = result.stdout
    print(f"Subprocess done: got {len(stdout)} bytes")


async def main():
    try:
        with fail_after(1):
            async with create_task_group() as tg:
                print("Starting")
                tg.start_soon(subprocess_output_no_stream)
            print("Task group done")
    except TimeoutError:
        print("Timed out!")


if __name__ == "__main__":
    run(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
1 participant