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

asyncio.run_coroutine_threadsafe drops specified exceptions' traceback #117459

Closed
rsp4jack opened this issue Apr 2, 2024 · 2 comments
Closed
Labels
type-bug An unexpected behavior, bug, or error

Comments

@rsp4jack
Copy link
Contributor

rsp4jack commented Apr 2, 2024

Bug report

Bug description:

import asyncio
import threading
import traceback

async def raiseme():
    raise ValueError(42)
async def raiseme2():
    raise asyncio.TimeoutError()

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
thr = threading.Thread(target=loop.run_forever, daemon=True)
thr.start()

print('raiseme() run_coroutine_threadsafe')
try:
    task = asyncio.run_coroutine_threadsafe(raiseme(), loop)
    task.result()
except:
    traceback.print_exc()

print('raiseme2() run_coroutine_threadsafe')
try:
    task = asyncio.run_coroutine_threadsafe(raiseme2(), loop)
    task.result()
except:
    traceback.print_exc()
raiseme() run_coroutine_threadsafe
Traceback (most recent call last):
  File "g:\Projects\NowPlaying\test.py", line 18, in <module>
    task.result()
  File "C:\Program Files\Python312\Lib\concurrent\futures\_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\concurrent\futures\_base.py", line 401, in __get_result
    raise self._exception
  File "g:\Projects\NowPlaying\test.py", line 6, in raiseme
    raise ValueError(42)
ValueError: 42
raiseme2() run_coroutine_threadsafe
Traceback (most recent call last):
  File "g:\Projects\NowPlaying\test.py", line 25, in <module>
    task.result()
  File "C:\Program Files\Python312\Lib\concurrent\futures\_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python312\Lib\concurrent\futures\_base.py", line 401, in __get_result
    raise self._exception
TimeoutError

The traceback of the second exception (TimeoutError) is dropeed.

The reason is that _convert_future_exc drops the origin exception's traceback:

def _convert_future_exc(exc):
exc_class = type(exc)
if exc_class is concurrent.futures.CancelledError:
return exceptions.CancelledError(*exc.args)
elif exc_class is concurrent.futures.TimeoutError:
return exceptions.TimeoutError(*exc.args)
elif exc_class is concurrent.futures.InvalidStateError:
return exceptions.InvalidStateError(*exc.args)
else:
return exc

To fix it, construct the new exception with the original traceback like that:

return exceptions.CancelledError(*exc.args).with_traceback(exc.__traceback__)

CPython versions tested on:

3.10, CPython main branch

Operating systems tested on:

Linux, Windows

Linked PRs

@rsp4jack rsp4jack added the type-bug An unexpected behavior, bug, or error label Apr 2, 2024
rsp4jack added a commit to rsp4jack/cpython that referenced this issue Apr 2, 2024
@graingert
Copy link
Contributor

The check for concurrent.futures.TimeoutError could be removed now that it's the same type as asyncio.TimeoutError

rsp4jack added a commit to rsp4jack/cpython that referenced this issue Apr 3, 2024
As python#117459 (comment) said, TimeoutError is a builtin exception now
@rsp4jack
Copy link
Contributor Author

rsp4jack commented Apr 3, 2024

@graingert Thanks, removed in 214f793

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants