Aiohttp: pytest-aiohttp + pytest-xdist cause RuntimeError: set_wakeup_fd só funciona na thread principal

Criado em 13 dez. 2018  ·  3Comentários  ·  Fonte: aio-libs/aiohttp

Longa história curta

Combinando pytest-aiohttp e pytest-xdist um erro é disparado às vezes do fixture loop .

Deixe-me saber se você acha que o problema está mais no lado pytest (-xdist).

Comportamento esperado

Sem erro.

Comportamento 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 ======================================================================================================

Passos para reproduzir

Copiei o mesmo arquivo de teste 10 vezes (apenas para ter alguns testes para trabalhar).

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

Eu uso o bash para executar o pytest várias vezes até que ele falhe:

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

Não sei por que, mas a sinalização detalhada parece afetá-lo: -v

Seu ambiente

Testado em 3.6 e 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

Comentários muito úteis

Obrigado pelo relatório.
xdist cria vários threads para executar o código testado, aiohttp deseja se inscrever no SIGINT e SIGTEM por padrão, mesmo se o thread não for o principal.

Podemos adicionar manipulação de sinais de salto se feito a partir do subthread (e gerar um aviso, claro).
Mas o verdadeiro problema é: semi-trabalho assíncio quando o segmento não é o principal.
Funciona perfeitamente bem em 98% dos casos, mas pode gerar resultados estranhos quando usado para sinais Unix ou subproceses.
Agora não tenho uma visão clara de como lidar com isso

Todos 3 comentários

GitMate.io acha que o contribuidor mais capaz de ajudá-lo é @asvetlov.

Possivelmente problemas relacionados são https://github.com/aio-libs/aiohttp/issues/2265 (RuntimeError: set_wakeup_fd funciona apenas no thread principal), https://github.com/aio-libs/aiohttp/issues/930 ( aiohttp.Timeout cause CancelledError), https://github.com/aio-libs/aiohttp/issues/841 (CTRL + C para parar não funciona em python -m aiohttp.web), https://github.com / aio-libs / aiohttp / issues / 3004 (Ctrl + C não funciona como exceto para aiohttp no Windows) e https://github.com/aio-libs/aiohttp/issues/3175 (tempo limite do cliente aiohttp não funciona) .

Obrigado pelo relatório.
xdist cria vários threads para executar o código testado, aiohttp deseja se inscrever no SIGINT e SIGTEM por padrão, mesmo se o thread não for o principal.

Podemos adicionar manipulação de sinais de salto se feito a partir do subthread (e gerar um aviso, claro).
Mas o verdadeiro problema é: semi-trabalho assíncio quando o segmento não é o principal.
Funciona perfeitamente bem em 98% dos casos, mas pode gerar resultados estranhos quando usado para sinais Unix ou subproceses.
Agora não tenho uma visão clara de como lidar com isso

Este tópico foi bloqueado automaticamente, pois não houve
qualquer atividade recente após ter sido fechada. Abra um [novo problema] para
bugs relacionados.

Se você sentir que há pontos importantes nesta discussão,
inclua essas exceções nessa [nova edição].

Esta página foi útil?
0 / 5 - 0 avaliações