O que causa o erro de tubo quebrado?

Eu sei que o erro de tubo quebrado é lançado quando o soquete no lado do par é fechado.

Mas, no meu teste, notei que uma chamada imediata de ‘envio’ deste lado, quando o lado de par está fechado, nem sempre leva a um erro de cano quebrado.

Por exemplo:

Depois de fechar o socket no peer side (tentei fechar limpo chamando close e também fechamento anormal matando o peer), se eu tentar enviar 40 bytes, então eu não consigo um pipe quebrado, mas, se eu tentar enviar 40000 bytes, em seguida, ele imediatamente dá erro de tubulação quebrada.

O que exatamente causa o cano quebrado e seu comportamento pode ser previsto?

Pode levar algum tempo para que a rede próxima seja observada – o tempo total é nominalmente cerca de 2 minutos (sim, minutos!) Depois de um fechamento antes que os pacotes destinados à porta sejam considerados mortos. A condição de erro é detectada em algum momento. Com uma gravação pequena, você está dentro da MTU do sistema, portanto, a mensagem é enfileirada para envio. Com uma gravação grande, você é maior que o MTU e o sistema identifica o problema mais rapidamente. Se você ignorar o sinal SIGPIPE, então as funções retornarão o erro EPIPE em um cano quebrado – em algum momento, quando a quebra da conexão for detectada.

O estado atual de um soquete é determinado pela atividade ‘keep-alive’. No seu caso, é possível que, quando você estiver emitindo a chamada de send , a atividade keep-alive informe que o soquete está ativo e, portanto, a chamada de send gravará os dados necessários (40 bytes) no buffer e retornará sem fornecer erro.

Quando você está enviando um pedaço maior, a chamada de envio entra no estado de bloqueio.

A página man send também confirma isso:

Quando a mensagem não se encheckbox no buffer de envio do socket, send () normalmente bloqueia, a menos que o socket tenha sido colocado no modo de E / S sem bloqueio. No modo sem bloqueio, retornaria EAGAIN neste caso

Portanto, enquanto estiver bloqueando o buffer disponível gratuitamente, se o chamador for notificado (pelo mecanismo keep-alive) de que a outra extremidade não está mais presente, a chamada de envio falhará.

Prever o cenário exato é difícil com as informações mencionadas, mas acredito que essa deve ser a razão do seu problema.

Talvez os 40 bytes caibam no buffer do pipe e os 40000 bytes não se encaixem?

Editar:

O processo de envio recebe um sinal SIGPIPE quando você tenta gravar em um canal fechado. Eu não sei exatamente quando o sinal é enviado, ou qual o efeito que o buffer do pipe tem sobre isso. Você pode recuperar-se prendendo o sinal com a chamada sigaction.