diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/uvloop/handles/handle.pyx')
-rw-r--r-- | venv/lib/python3.11/site-packages/uvloop/handles/handle.pyx | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/venv/lib/python3.11/site-packages/uvloop/handles/handle.pyx b/venv/lib/python3.11/site-packages/uvloop/handles/handle.pyx deleted file mode 100644 index 6efe375..0000000 --- a/venv/lib/python3.11/site-packages/uvloop/handles/handle.pyx +++ /dev/null @@ -1,395 +0,0 @@ -cdef class UVHandle: - """A base class for all libuv handles. - - Automatically manages memory deallocation and closing. - - Important: - - 1. call "_ensure_alive()" before calling any libuv functions on - your handles. - - 2. call "__ensure_handle_data" in *all* libuv handle callbacks. - """ - - def __cinit__(self): - self._closed = 0 - self._inited = 0 - self._has_handle = 1 - self._handle = NULL - self._loop = None - self._source_traceback = None - - def __init__(self): - raise TypeError( - '{} is not supposed to be instantiated from Python'.format( - self.__class__.__name__)) - - def __dealloc__(self): - if UVLOOP_DEBUG: - if self._loop is not None: - if self._inited: - self._loop._debug_handles_current.subtract([ - self.__class__.__name__]) - else: - # No "@cython.no_gc_clear" decorator on this UVHandle - raise RuntimeError( - '{} without @no_gc_clear; loop was set to None by GC' - .format(self.__class__.__name__)) - - if self._handle is NULL: - return - - # -> When we're at this point, something is wrong <- - - if self._handle.loop is NULL: - # The handle wasn't initialized with "uv_{handle}_init" - self._closed = 1 - self._free() - raise RuntimeError( - '{} is open in __dealloc__ with loop set to NULL' - .format(self.__class__.__name__)) - - if self._closed: - # So _handle is not NULL and self._closed == 1? - raise RuntimeError( - '{}.__dealloc__: _handle is NULL, _closed == 1'.format( - self.__class__.__name__)) - - # The handle is dealloced while open. Let's try to close it. - # Situations when this is possible include unhandled exceptions, - # errors during Handle.__cinit__/__init__ etc. - if self._inited: - self._handle.data = NULL - uv.uv_close(self._handle, __uv_close_handle_cb) # void; no errors - self._handle = NULL - self._warn_unclosed() - else: - # The handle was allocated, but not initialized - self._closed = 1 - self._free() - - cdef _free(self): - if self._handle == NULL: - return - - if UVLOOP_DEBUG and self._inited: - self._loop._debug_uv_handles_freed += 1 - - PyMem_RawFree(self._handle) - self._handle = NULL - - cdef _warn_unclosed(self): - if self._source_traceback is not None: - try: - tb = ''.join(tb_format_list(self._source_traceback)) - tb = 'object created at (most recent call last):\n{}'.format( - tb.rstrip()) - except Exception as ex: - msg = ( - 'unclosed resource {!r}; could not serialize ' - 'debug traceback: {}: {}' - ).format(self, type(ex).__name__, ex) - else: - msg = 'unclosed resource {!r}; {}'.format(self, tb) - else: - msg = 'unclosed resource {!r}'.format(self) - warnings_warn(msg, ResourceWarning) - - cdef inline _abort_init(self): - if self._handle is not NULL: - self._free() - - try: - if UVLOOP_DEBUG: - name = self.__class__.__name__ - if self._inited: - raise RuntimeError( - '_abort_init: {}._inited is set'.format(name)) - if self._closed: - raise RuntimeError( - '_abort_init: {}._closed is set'.format(name)) - finally: - self._closed = 1 - - cdef inline _finish_init(self): - self._inited = 1 - if self._has_handle == 1: - self._handle.data = <void*>self - if self._loop._debug: - self._source_traceback = extract_stack() - if UVLOOP_DEBUG: - cls_name = self.__class__.__name__ - self._loop._debug_uv_handles_total += 1 - self._loop._debug_handles_total.update([cls_name]) - self._loop._debug_handles_current.update([cls_name]) - - cdef inline _start_init(self, Loop loop): - if UVLOOP_DEBUG: - if self._loop is not None: - raise RuntimeError( - '{}._start_init can only be called once'.format( - self.__class__.__name__)) - - self._loop = loop - - cdef inline bint _is_alive(self): - cdef bint res - res = self._closed != 1 and self._inited == 1 - if UVLOOP_DEBUG: - if res and self._has_handle == 1: - name = self.__class__.__name__ - if self._handle is NULL: - raise RuntimeError( - '{} is alive, but _handle is NULL'.format(name)) - if self._loop is None: - raise RuntimeError( - '{} is alive, but _loop is None'.format(name)) - if self._handle.loop is not self._loop.uvloop: - raise RuntimeError( - '{} is alive, but _handle.loop is not ' - 'initialized'.format(name)) - if self._handle.data is not <void*>self: - raise RuntimeError( - '{} is alive, but _handle.data is not ' - 'initialized'.format(name)) - return res - - cdef inline _ensure_alive(self): - if not self._is_alive(): - raise RuntimeError( - 'unable to perform operation on {!r}; ' - 'the handler is closed'.format(self)) - - cdef _fatal_error(self, exc, throw, reason=None): - # Fatal error means an error that was returned by the - # underlying libuv handle function. We usually can't - # recover from that, hence we just close the handle. - self._close() - - if throw or self._loop is None: - raise exc - else: - self._loop._handle_exception(exc) - - cdef _error(self, exc, throw): - # A non-fatal error is usually an error that was caught - # by the handler, but was originated in the client code - # (not in libuv). In this case we either want to simply - # raise or log it. - if throw or self._loop is None: - raise exc - else: - self._loop._handle_exception(exc) - - cdef _close(self): - if self._closed == 1: - return - - self._closed = 1 - - if self._handle is NULL: - return - - if UVLOOP_DEBUG: - if self._handle.data is NULL: - raise RuntimeError( - '{}._close: _handle.data is NULL'.format( - self.__class__.__name__)) - - if <object>self._handle.data is not self: - raise RuntimeError( - '{}._close: _handle.data is not UVHandle/self'.format( - self.__class__.__name__)) - - if uv.uv_is_closing(self._handle): - raise RuntimeError( - '{}._close: uv_is_closing() is true'.format( - self.__class__.__name__)) - - # We want the handle wrapper (UVHandle) to stay alive until - # the closing callback fires. - Py_INCREF(self) - uv.uv_close(self._handle, __uv_close_handle_cb) # void; no errors - - def __repr__(self): - return '<{} closed={} {:#x}>'.format( - self.__class__.__name__, - self._closed, - id(self)) - - -cdef class UVSocketHandle(UVHandle): - - def __cinit__(self): - self._fileobj = None - self.__cached_socket = None - - cdef _fileno(self): - cdef: - int fd - int err - - self._ensure_alive() - err = uv.uv_fileno(self._handle, <uv.uv_os_fd_t*>&fd) - if err < 0: - raise convert_error(err) - - return fd - - cdef _new_socket(self): - raise NotImplementedError - - cdef inline _get_socket(self): - if self.__cached_socket is not None: - return self.__cached_socket - - if not self._is_alive(): - return None - - self.__cached_socket = self._new_socket() - if UVLOOP_DEBUG: - # We don't "dup" for the "__cached_socket". - assert self.__cached_socket.fileno() == self._fileno() - return self.__cached_socket - - cdef inline _attach_fileobj(self, object file): - # When we create a TCP/PIPE/etc connection/server based on - # a Python file object, we need to close the file object when - # the uv handle is closed. - socket_inc_io_ref(file) - self._fileobj = file - - cdef _close(self): - if self.__cached_socket is not None: - (<PseudoSocket>self.__cached_socket)._fd = -1 - - UVHandle._close(self) - - try: - # This code will only run for transports created from - # Python sockets, i.e. with `loop.create_server(sock=sock)` etc. - if self._fileobj is not None: - if isinstance(self._fileobj, socket_socket): - # Detaching the socket object is the ideal solution: - # * libuv will actually close the FD; - # * detach() call will reset FD for the Python socket - # object, which means that it won't be closed 2nd time - # when the socket object is GCed. - # - # No need to call `socket_dec_io_ref()`, as - # `socket.detach()` ignores `socket._io_refs`. - self._fileobj.detach() - else: - try: - # `socket.close()` will raise an EBADF because libuv - # has already closed the underlying FD. - self._fileobj.close() - except OSError as ex: - if ex.errno != errno_EBADF: - raise - except Exception as ex: - self._loop.call_exception_handler({ - 'exception': ex, - 'transport': self, - 'message': f'could not close attached file object ' - f'{self._fileobj!r}', - }) - finally: - self._fileobj = None - - cdef _open(self, int sockfd): - raise NotImplementedError - - -cdef inline bint __ensure_handle_data(uv.uv_handle_t* handle, - const char* handle_ctx): - - cdef Loop loop - - if UVLOOP_DEBUG: - if handle.loop is NULL: - raise RuntimeError( - 'handle.loop is NULL in __ensure_handle_data') - - if handle.loop.data is NULL: - raise RuntimeError( - 'handle.loop.data is NULL in __ensure_handle_data') - - if handle.data is NULL: - loop = <Loop>handle.loop.data - loop.call_exception_handler({ - 'message': '{} called with handle.data == NULL'.format( - handle_ctx.decode('latin-1')) - }) - return 0 - - if handle.data is NULL: - # The underlying UVHandle object was GCed with an open uv_handle_t. - loop = <Loop>handle.loop.data - loop.call_exception_handler({ - 'message': '{} called after destroying the UVHandle'.format( - handle_ctx.decode('latin-1')) - }) - return 0 - - return 1 - - -cdef void __uv_close_handle_cb(uv.uv_handle_t* handle) noexcept with gil: - cdef UVHandle h - - if handle.data is NULL: - # The original UVHandle is long dead. Just free the mem of - # the uv_handle_t* handler. - - if UVLOOP_DEBUG: - if handle.loop == NULL or handle.loop.data == NULL: - raise RuntimeError( - '__uv_close_handle_cb: handle.loop is invalid') - (<Loop>handle.loop.data)._debug_uv_handles_freed += 1 - - PyMem_RawFree(handle) - else: - h = <UVHandle>handle.data - try: - if UVLOOP_DEBUG: - if not h._has_handle: - raise RuntimeError( - 'has_handle=0 in __uv_close_handle_cb') - h._loop._debug_handles_closed.update([ - h.__class__.__name__]) - h._free() - finally: - Py_DECREF(h) # Was INCREFed in UVHandle._close - - -cdef void __close_all_handles(Loop loop): - uv.uv_walk(loop.uvloop, - __uv_walk_close_all_handles_cb, - <void*>loop) # void - - -cdef void __uv_walk_close_all_handles_cb( - uv.uv_handle_t* handle, - void* arg, -) noexcept with gil: - - cdef: - Loop loop = <Loop>arg - UVHandle h - - if uv.uv_is_closing(handle): - # The handle is closed or is closing. - return - - if handle.data is NULL: - # This shouldn't happen. Ever. - loop.call_exception_handler({ - 'message': 'handle.data is NULL in __close_all_handles_cb' - }) - return - - h = <UVHandle>handle.data - if not h._closed: - h._warn_unclosed() - h._close() |