Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Description
Bug report
Bug description:
Running the code below yields many lines of unwanted error output of the kind
Loop <_UnixSelectorEventLoop running=False closed=True debug=False> that handles pid 842379 is closed
and also runtime exceptionsafter all user code has completed of the kind
Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x7f9558756340>Traceback (most recent call last): File "/usr/lib64/python3.11/asyncio/base_subprocess.py", line 126, in __del__ self.close() File "/usr/lib64/python3.11/asyncio/base_subprocess.py", line 104, in close proto.pipe.close() File "/usr/lib64/python3.11/asyncio/unix_events.py", line 566, in close self._close(None) File "/usr/lib64/python3.11/asyncio/unix_events.py", line 590, in _close self._loop.call_soon(self._call_connection_lost, exc) File "/usr/lib64/python3.11/asyncio/base_events.py", line 761, in call_soon self._check_closed() File "/usr/lib64/python3.11/asyncio/base_events.py", line 519, in _check_closed raise RuntimeError('Event loop is closed')RuntimeError: Event loop is closed
This apparently is caused by havingasyncio.wait_for
with aTIMEOUT_SECS
at an absurdly low value - which is that low to be able toreliably provoke the problem - IOW, this misbehaviour seems to depend on timeout errors being raised.
Of particular note is thetime.sleep(2)
at the end which I use to delay process termination; this makes the problemvisible on stderr. Note that the exit code of the Python process is always 0 (watch --errexit --interval=0 python debugger-bug.py
).
The implementation is cobbled together from an example in the Python documentation (with fixes applied) and from StackOverflow for throttling best practices with aSemaphore
.
I am running this on Fedora Linux 38, Python 3.11.5, on an Intel 11800H CPU, lots of memory spare, within VMware Workstation.
importasyncioimportsysimporttimeTASK_COUNT:int=50TASK_THROTTLE_COUNT:int=7TIMEOUT_SECS:float=0.00001asyncdefget_date(i:int)->str:# print(f"Starting task #{i}")code="import datetime; print(datetime.datetime.now())"proc=awaitasyncio.create_subprocess_exec(sys.executable,"-c",code,stdout=asyncio.subprocess.PIPE )try:stdout,_=awaitasyncio.wait_for(proc.communicate(),TIMEOUT_SECS)exceptasyncio.TimeoutError:return"TIMEOUT"line=stdout.decode("ascii").rstrip()# Wait for the subprocess exit.awaitproc.wait()returnlineasyncdefthrottled_get_date(sem:asyncio.Semaphore,i:int):asyncwithsem:# semaphore limits num of simultaneous downloadsreturnawaitget_date(i)asyncdefrun_throttled():sem=asyncio.Semaphore(TASK_THROTTLE_COUNT)tasks= [asyncio.create_task(throttled_get_date(sem,i))foriinrange(TASK_COUNT)]returnawaitasyncio.gather(*tasks)asyncdefrun_unthrottled():tasks= [asyncio.create_task(get_date(i))foriinrange(TASK_COUNT)]returnawaitasyncio.gather(*tasks)defshell_to_get_date():start=time.time()date=asyncio.run(run_throttled())duration=time.time()-startprint(f"Current dates:{date} -{duration} secs")iflen(date)!=TASK_COUNT:raiseExceptionif__name__=="__main__":shell_to_get_date()print("done")time.sleep(2)
CPython versions tested on:
3.11
Operating systems tested on:
Linux
Metadata
Metadata
Assignees
Projects
Status