Estou trabalhando em um script python3 que manipula sinais (por exemplo, signal.SIGWINCH
) colocando-os em uma fila. Uma thread separada coloca a entrada do usuário na mesma fila, que é toda processada pela thread principal do meu programa.
Ocasionalmente, o programa inteiro trava repentinamente. Identifiquei a causa como sendo a interação entre os manipuladores de sinais e a queue.Queue
classe. Após um pequeno número aleatório de sinais ser enfileirado, o manipulador de sinais bloqueia a fila ao tentar inserir um item nela. Qualquer thread que tente interagir com a fila de qualquer forma (por exemplo, chamando queue.put(block=False)
, queue.get(block=False)
ou queue.empty()
) também trava.
Por que os manipuladores de sinais bloqueiam minha fila, mesmo quando uso funções não bloqueantes? Existe uma maneira segura de adicionar sinais a uma fila em um programa multithread?
Isso pode ser reproduzido executando o trecho de código simplificado abaixo, enquanto redimensiona repetidamente o terminal para acionar o evento (testado em python 3.13, linux):
from queue import Queue, Empty
import signal
event_queue = Queue()
def signal_handler(signum, frame):
event_queue.put(signum)
signal.signal(signal.SIGWINCH, signal_handler)
while True:
try:
print("Attempting to get an event from the queue...")
evt = event_queue.get(block=False)
print("Successfully got event from the queue.")
except Empty:
print("The queue is empty, try again.")
Eventualmente, após redimensionar a janela um número indeterminado de vezes, o código trava após a linha "Tentando obter um evento da fila..."; ou seja, trava em queue.get()
. Mas não deveria, já que especifiquei block=False
. Também tentei usar event_queue.put(signum, block=False)
no meu manipulador de sinais dentro de um try/except, mas ainda trava.
(...)
Attempting to get an event from the queue...
The queue is empty, try again.
Attempting to get an event from the queue...
(code hangs indefinitely)
Se eu mudar para multiprocessing.Queue
ou usar queue.get(timeout=0.1)
, aparentemente não terei mais esse problema. Mas ambas as abordagens têm um custo/atraso de velocidade substancial, e estou preocupado se alguma delas é totalmente segura, já que até mesmo queue.Queue
é supostamente seguro para threads .