Posso esperar por uma das várias conexões de rede usando select
ou epoll
. Posso esperar por um sinal usando sigwaitinfo
ou adicionar um manipulador para executar no recebimento do sinal.
Como posso esperar que um soquete de rede tenha tráfego de entrada ou um sinal específico (SIGWINCH, no meu caso)?
Uma ideia que me ocorre é fazer com que o manipulador de sinal envie tráfego "loopback" para algum descritor de arquivo aberto, para que epoll
possa aguardá-lo. Mas eu preferiria não criar nenhum arquivo. Talvez haja uma maneira de criar dois novos descritores de arquivo que sejam conectados diretamente um ao outro?
No Linux, eu faria isso com
signalfd(2)
, que cria um descritor de arquivo que pesquisa como legível quando sinais dados são entregues (e pode ser lido para descobrir informações sobre o sinal). Esse descritor pode ser adicionado aos monitorados porepoll
, junto com os sockets.Você deve bloquear
SIGWINCH
primeiro parasigprocmask(2)
que ele não seja manipulado pelos manipuladores de sinais normais.Você pode usar
pipe(2)
para criar um par de descritores conectados para esse estilo; é uma técnica comum para esse tipo de cenário em bases de código mais antigas e/ou portáteis. Com Linux, geralmente prefiro o peso mais leveeventfd(2)
para notificações assíncronas.Você tem várias opções para um único thread responder tanto a sinais quanto a E/S.
1. Transforme os sinais em E/S
Essa é a abordagem que você pensou, e que outra resposta cobre bem. Você tem o velho (e portátil) truque do self-pipe e o . específico do Linux
signalfd
.É isso que eu faria e sugeriria votar positivamente e aceitar a outra resposta.
2. Transforme as E/S em sinais
Para completar, vale mencionar que você pode usar o comando
fcntl
para gerenciar sinais , usando F_SETOWN e O_ASYNC para obter um SIGIO entregue quando um descritor estiver pronto para leitura ou escrita.Com SA_SIGINFO e, no Linux, um F_SETSIG explícito , você poderá dizer qual descritor está pronto e por quê.
Definitivamente mais estranho que o #1 e talvez inapropriado se alguns dos seus descritores forem perpetuamente graváveis, por exemplo. Mas pode funcionar bem para, por exemplo, esperar por conexões de entrada em um socket vinculado.
3. Manipule sinais e E/S separadamente, com mascaramento atômico
POSIX
pselect
e Linuxppoll
permitem que você use multiplexação de E/S sem "perder" um sinal, desbloqueando atomicamente os sinais desejados somente durante a chamada de multiplexação.Importante,
select
epoll
são propensas à raça aqui, que outras perguntas neste site abordam.