MagicStack / MagicStack/uvloop

OSError: [Errno 6] No such device or address: '/proc/self/fd/1' when using asyncio.create_subprocess_*

Aberta
#505 1 comentário 2 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

Linguagem predominante
Cython
Estrelas
11.9k
Forks
616
Métricas de merge de PRs
Nenhum PR com merge em 30d

Descrição

  • uvloop==0.16.0 and uvloop==0.17.0:
  • python3.8.10 and python3.10.5:
  • Platform: Ubuntu20.04:
  • Can you reproduce the bug with PYTHONASYNCIODEBUG in env? -> Yes, but there is not more output:
  • Does uvloop behave differently from vanilla asyncio? How? It uses socket instead of pipe for the file descriptors of the subprocess. This gives me an OSError6:

Uvloop does not handle subprocess pipes properly. It doesn not matter if I use asyncio.subprocess.PIPE or subprocess.PIPE. How can I access stdout/stderr of a asyncio subprocess? Is this behavior intended?

Running the proof of concept:

import asyncio, subprocess
async def poc():
    proc = await asyncio.create_subprocess_shell(
        "ls -lsh /proc/self/fd",
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate()
    print(stdout, stderr)
    proc = await asyncio.create_subprocess_shell(
        "python3 -c \"f=open('/proc/self/fd/1', 'w'); f.write('test')\"", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
    )
    stdout, stderr = await proc.communicate()
    print(stdout, stderr)

async def poc1():
    proc = await asyncio.create_subprocess_shell(
        "ls -lsh /proc/self/fd",
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate()
    print(stdout, stderr)
    proc = await asyncio.create_subprocess_shell(
        "python3 -c \"f=open('/proc/self/fd/1', 'w'); f.write('test')\"", stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    stdout, stderr = await proc.communicate()
    print(stdout, stderr)

print("Default loop")
asyncio.run(poc())
asyncio.run(poc1())

import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

print("uvloop")
print("asyncio pipe")
asyncio.run(poc())
print("subprocess pipe")
asyncio.run(poc1())

Yields the following output:

Default loop
b'total 0\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 0 -> /dev/pts/10\n0 l-wx------ 1 peter peter 64 Sep 22 12:19 1 -> pipe:[8435934]\n0 l-wx------ 1 peter peter 64 Sep 22 12:19 2 -> pipe:[8435935]\n0 lr-x------ 1 peter peter 64 Sep 22 12:19 3 -> /proc/625365/fd\n' b''
b'test' b''
b'total 0\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 0 -> /dev/pts/10\n0 l-wx------ 1 peter peter 64 Sep 22 12:19 1 -> pipe:[8435942]\n0 l-wx------ 1 peter peter 64 Sep 22 12:19 2 -> pipe:[8435943]\n0 lr-x------ 1 peter peter 64 Sep 22 12:19 3 -> /proc/625371/fd\n' b''
b'test' b''
uvloop
asyncio pipe
b'total 0\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 0 -> /dev/pts/10\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 1 -> socket:[8435953]\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 2 -> socket:[8435955]\n0 lr-x------ 1 peter peter 64 Sep 22 12:19 3 -> /proc/625376/fd\n' b''
b'' b'Traceback (most recent call last):\n  File "<string>", line 1, in <module>\nOSError: [Errno 6] No such device or address: \'/proc/self/fd/1\'\n'
subprocess pipe
b'total 0\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 0 -> /dev/pts/10\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 1 -> socket:[8396454]\n0 lrwx------ 1 peter peter 64 Sep 22 12:19 2 -> socket:[8396456]\n0 lr-x------ 1 peter peter 64 Sep 22 12:19 3 -> /proc/625380/fd\n' b''
b'' b'Traceback (most recent call last):\n  File "<string>", line 1, in <module>\nOSError: [Errno 6] No such device or address: \'/proc/self/fd/1\'\n'

As we can see, once uvloop is running the calls that worked earlier are crashing. The observable difference is that uvloop maps sockets to stdout/stderr whereas default asyncio uses pipes

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece executando a prova de conceito fornecida com vanilla asyncio e uvloop, concentrando-se em asyncio.create_subprocess_shell, no tratamento de PIPE e em uvloop.EventLoopPolicy. Compare os descritores de arquivo de stdout e stderr e a saída de erro; considera-se concluído quando o comportamento relatado do pipe do subprocesso for compreendido e a reprodução não produzir mais o OSError.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
networking
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
38/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.