Esempio n. 1
0
    def copy_tb(base_tb, tb_next):
        # TracebackType has no public constructor, so allocate one the hard way
        try:
            raise ValueError
        except ValueError as exc:
            new_tb = exc.__traceback__
        c_new_tb = CTraceback.from_address(id(new_tb))

        # At the C level, tb_next either pointer to the next traceback or is
        # NULL. c_void_p and the .tb_next accessor both convert NULL to None,
        # but we shouldn't DECREF None just because we assigned to a NULL
        # pointer! Here we know that our new traceback has only 1 frame in it,
        # so we can assume the tb_next field is NULL.
        assert c_new_tb.tb_next is None
        # If tb_next is None, then we want to set c_new_tb.tb_next to NULL,
        # which it already is, so we're done. Otherwise, we have to actually
        # do some work:
        if tb_next is not None:
            _ctypes.Py_INCREF(tb_next)
            c_new_tb.tb_next = id(tb_next)

        assert c_new_tb.tb_frame is not None
        _ctypes.Py_INCREF(base_tb.tb_frame)
        old_tb_frame = new_tb.tb_frame
        c_new_tb.tb_frame = id(base_tb.tb_frame)
        _ctypes.Py_DECREF(old_tb_frame)

        c_new_tb.tb_lasti = base_tb.tb_lasti
        c_new_tb.tb_lineno = base_tb.tb_lineno

        return new_tb
Esempio n. 2
0
def set_aio_task_coro(
    task: "asyncio.Task[Any]", new_coro: Coroutine[Any, Any, Any]
) -> None:
    try:
        task._coro = new_coro  # type: ignore
        return
    except AttributeError as ex:
        if sys.implementation.name != "cpython":  # pragma: no cover
            raise
        if "is not writable" not in str(ex):  # pragma: no cover
            raise

    # If using the C accelerator on CPython, the setter isn't
    # even present and we need to use ctypes to change the
    # coroutine field.

    global aio_task_coro_c_offset
    import ctypes

    old_coro = get_aio_task_coro(task)

    if aio_task_coro_c_offset is None:
        # Deduce the offset by scanning the task object representation
        # for id(task._coro)
        aio_task_coro_c_offset = _aligned_ptr_offset_in_object(task, old_coro)
        if aio_task_coro_c_offset is None:  # pragma: no cover
            raise RuntimeError("Couldn't determine C offset of asyncio.Task._coro")

    # (Explanation copied from trio._core._multierror, applies equally well here.)
    # How to handle refcounting? I don't want to use ctypes.py_object because
    # I don't understand or trust it, and I don't want to use
    # ctypes.pythonapi.Py_{Inc,Dec}Ref because we might clash with user code
    # that also tries to use them but with different types. So private _ctypes
    # APIs it is!
    import _ctypes  # type: ignore

    coro_field = ctypes.c_size_t.from_address(id(task) + aio_task_coro_c_offset)
    assert coro_field.value == id(old_coro)
    _ctypes.Py_INCREF(new_coro)
    coro_field.value = id(new_coro)
    _ctypes.Py_DECREF(old_coro)