Aiohttp: pytest-aiohttp + pytest-xdist causa RuntimeError: set_wakeup_fd solo funciona en el hilo principal

Creado en 13 dic. 2018  ·  3Comentarios  ·  Fuente: aio-libs/aiohttp

Larga historia corta

Al combinar pytest-aiohttp y pytest-xdist veces se desencadena un error desde el accesorio loop .

Avísame si crees que el problema está más en el lado de pytest (-xdist).

Comportamiento esperado

No hay error.

Comportamiento real

=================================================================================================================== ERRORS ====================================================================================================================
_____________________________________________________________________________________________________ ERROR at setup of test_foo[pyloop] ______________________________________________________________________________________________________
[gw6] linux -- Python 3.7.0 /home/merlin/workspace/pytest-test/.venv/bin/python3.7

loop_factory = <class 'asyncio.unix_events._UnixDefaultEventLoopPolicy'>, fast = False, loop_debug = False

    @pytest.fixture
    def loop(loop_factory, fast, loop_debug):
        """Return an instance of the event loop."""
        policy = loop_factory()
        asyncio.set_event_loop_policy(policy)
>       with loop_context(fast=fast) as _loop:

.venv/lib/python3.7/site-packages/aiohttp/pytest_plugin.py:205:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.7/contextlib.py:112: in __enter__
    return next(self.gen)
.venv/lib/python3.7/site-packages/aiohttp/test_utils.py:404: in loop_context
    loop = setup_test_loop(loop_factory)
.venv/lib/python3.7/site-packages/aiohttp/test_utils.py:427: in setup_test_loop
    watcher.attach_loop(loop)
/usr/local/lib/python3.7/asyncio/unix_events.py:868: in attach_loop
    loop.add_signal_handler(signal.SIGCHLD, self._sig_chld)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <_UnixSelectorEventLoop running=False closed=False debug=False>, sig = <Signals.SIGCHLD: 17>, callback = <bound method BaseChildWatcher._sig_chld of <asyncio.unix_events.SafeChildWatcher object at 0x7fbf10c9b048>>, args = ()

    def add_signal_handler(self, sig, callback, *args):
        """Add a handler for a signal.  UNIX only.

        Raise ValueError if the signal number is invalid or uncatchable.
        Raise RuntimeError if there is a problem setting up the handler.
        """
        if (coroutines.iscoroutine(callback) or
                coroutines.iscoroutinefunction(callback)):
            raise TypeError("coroutines cannot be used "
                            "with add_signal_handler()")
        self._check_signal(sig)
        self._check_closed()
        try:
            # set_wakeup_fd() raises ValueError if this is not the
            # main thread.  By calling it early we ensure that an
            # event loop running in another thread cannot add a signal
            # handler.
            signal.set_wakeup_fd(self._csock.fileno())
        except (ValueError, OSError) as exc:
>           raise RuntimeError(str(exc))
E           RuntimeError: set_wakeup_fd only works in main thread

/usr/local/lib/python3.7/asyncio/unix_events.py:94: RuntimeError
===================================================================================================== 10 passed, 1 error in 0.93 seconds ======================================================================================================

pasos para reproducir

He copiado el mismo archivo de prueba 10 veces (solo para tener algunas pruebas con las que trabajar).

async def test_foo(loop):
    assert 42 == 42

Utilizo bash para ejecutar pytest varias veces hasta que falla:

while pytest tests/ -n auto -v; do :; done

No estoy seguro de por qué, pero la bandera detallada parece afectarlo: -v

Tu entorno

Probado en 3.6 y 3.7.
CPU de 8 núcleos

Python 3.6.7
Python 3.7.0b5
aiohttp==3.4.4
pytest==4.0.1
pytest-aiohttp==0.3.0
pytest-xdist==1.25.0
bug outdated

Comentario más útil

Gracias por el informe.
xdist crea varios subprocesos para ejecutar el código probado, aiohttp quiere suscribirse a SIGINT y SIGTEM de forma predeterminada, incluso si el subproceso no es el principal.

Podemos agregar el manejo de señales de omisión si se hace desde un subproceso (y generar una advertencia, seguro).
Pero el problema real es: asyncio semi-trabajando cuando el hilo no es el principal.
Funciona perfectamente bien en el 98% de los casos, pero puede generar resultados extraños cuando se usa para señales o subprocesos Unix.
Ahora no tengo una visión clara de cómo manejarlo

Todos 3 comentarios

GitMate.io cree que el colaborador que probablemente pueda ayudarte es @asvetlov.

Posiblemente los problemas relacionados son https://github.com/aio-libs/aiohttp/issues/2265 (RuntimeError: set_wakeup_fd solo funciona en el hilo principal), https://github.com/aio-libs/aiohttp/issues/930 ( aiohttp.Timeout provoca CancelledError), https://github.com/aio-libs/aiohttp/issues/841 (CTRL + C para detener no funciona en python -m aiohttp.web), https://github.com / aio-libs / aiohttp / issues / 3004 (Ctrl + C no funciona excepto para aiohttp en Windows) y https://github.com/aio-libs/aiohttp/issues/3175 (el tiempo de espera del cliente aiohttp no funciona) .

Gracias por el informe.
xdist crea varios subprocesos para ejecutar el código probado, aiohttp quiere suscribirse a SIGINT y SIGTEM de forma predeterminada, incluso si el subproceso no es el principal.

Podemos agregar el manejo de señales de omisión si se hace desde un subproceso (y generar una advertencia, seguro).
Pero el problema real es: asyncio semi-trabajando cuando el hilo no es el principal.
Funciona perfectamente bien en el 98% de los casos, pero puede generar resultados extraños cuando se usa para señales o subprocesos Unix.
Ahora no tengo una visión clara de cómo manejarlo

Este hilo se ha bloqueado automáticamente ya que no ha habido
cualquier actividad reciente después de su cierre. Abra un [número nuevo] para
errores relacionados.

Si cree que se han hecho puntos importantes en esta discusión,
incluya esas excepciones en ese [nuevo número].

¿Fue útil esta página
0 / 5 - 0 calificaciones