mkfifo pipes, descritores de arquivos e ImageMagick (convert)

3

Estou com problemas ao usar pipes nomeados (ou seja, criados com mkfifo ) e descritores de arquivos para redirecionar as saídas e obter entradas para / a partir deles no ImageMagick ( convert ).

Basicamente, com o seguinte código bash (bem, um equivalente mais fácil ao que estou tentando), o script trava e não mostra a imagem:

#!/bin/bash
mkfifo myPipe                              # Create a named pipe
exec 3<>myPipe                             # I/O file descriptor using the pipe
convert rose: -resize 640x480\! png:fd:3   # Write the image to the pipe
convert png:fd:3 win:                      # To read from the pipe using the file descriptor
exec 3>&-                                  # Close the file descriptor
rm myPipe                                  # Close and remove the pipe

Fazendo algumas pesquisas, eu vi aqui este parágrafo (é da resposta de Jonathan Leffler):

When a FIFO is opened for reading, it blocks the calling process (normally). When a process opens the FIFO for writing, then the reader is unblocked. When the writer closes the FIFO, the reading process gets EOF (0 bytes to read), and there is nothing further that can be done except close the FIFO and reopen.

Para evitar isso, tentei usar a solução de Mark Edgar que consiste nessas instruções (código retirado da resposta):

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Open pipe for writing.
exec 3>pipe
echo one >&3
echo two >&3
# Close pipe.
exec 3>&-

Infelizmente, preciso ler o pipe e escrever nele com descritores de arquivo (por exemplo, fd:X using convert ). Como posso conseguir isso sem os problemas pendentes?

    
por JBFWP286 23.04.2016 / 07:27

1 resposta

4

O problema é que, enquanto

exec 3<>myPipe

abre ambos os lados R e W do FIFO simultaneamente, evitando assim um deadlock,

convert rose: -resize 640x480\! png:fd:3

é um comando normal / em primeiro plano que precisa ser concluído antes que o próximo comando possa ser executado. Como está escrevendo o que provavelmente será um monte de dados para um FIFO, ele não será concluído, mas será bloqueado quando o buffer FIFO estiver cheio, bloqueando efetivamente o script.

Para evitar isso, você precisa colocar este comando em segundo plano para que o próximo processo possa drenar simultaneamente o FIFO, evitando que ele se encha.

Como mencionei no comentário, neste caso, recomendo usar canais regulares em vez de pipes nomeados:

convert rose: -resize 640x480\! png:fd:1 | 
   convert png:fd:0 win:

Se você estiver preocupado com o fato de suas linhas de código ficarem muito longas, crie linhas de continuação finalizando linhas com \ ou colocando novas linhas após os tokens que precisam do lado direito (como || , && , ou | como eu fiz isso) (Eu também tendem a recuar minhas linhas de continuação para melhor legibilidade, mas isso é puramente opcional).

    
por 23.04.2016 / 07:57