Che cosa causa l’errore del tubo rotto?

So che l’errore del tubo rotto viene generato quando la presa sul lato pari è chiusa.

Ma nel mio test ho notato che un’immediata chiamata “invia” su questo lato quando il lato pari è chiuso non sempre causa un errore di tubo rotto.

Per esempio:

Dopo aver chiuso il socket sul peer side (ho provato a chiudere in modo pulito chiamando close e chiudendo anormalmente uccidendo il peer), se provo a inviare 40 byte, quindi non ottengo un pipe rotto, ma, se provo a invia 40000 byte, quindi dà immediatamente errore di tubo rotto.

Cosa provoca esattamente la rottura della tubazione e può essere previsto il suo comportamento?

Può essere necessario del tempo per osservare la rete da osservare: il tempo totale è nominale di circa 2 minuti (sì, minuti!) Dopo una chiusura prima che i pacchetti destinati alla porta siano tutti considerati morti. La condizione di errore viene rilevata ad un certo punto. Con una piccola scrittura, ci si trova all’interno della MTU del sistema, quindi il messaggio viene accodato per l’invio. Con una grande scrittura, sei più grande della MTU e il sistema individua il problema più rapidamente. Se ignori il segnale SIGPIPE, le funzioni restituiranno l’errore EPIPE su una pipe rotta – ad un certo punto quando viene rilevata la rottura della connessione.

Lo stato corrente di un socket è determinato dall’attività “keep-alive”. Nel tuo caso, è ansible che durante l’emissione della chiamata di send , l’attività keep-alive indichi che il socket è attivo e quindi la chiamata di send scriverà i dati richiesti (40 byte) nel buffer e restituirà senza dare alcun errore.

Quando si invia un blocco più grande, la chiamata di invio passa allo stato di blocco.

Anche la pagina man di send lo conferma:

Quando il messaggio non si adatta al buffer di invio del socket, send () normalmente blocca, a meno che il socket non sia stato inserito in modalità I / O non bloccante. In modalità non bloccante restituirà EAGAIN in questo caso

Quindi, mentre si blocca il buffer libero disponibile, se il chiamante riceve notifica (tramite meccanismo keep-alive) che l’altra estremità non è più presente, la chiamata di invio avrà esito negativo.

Prevedere lo scenario esatto è difficile con le informazioni menzionate, ma credo che questo dovrebbe essere il motivo del tuo problema.

Forse i 40 byte si inseriscono nel buffer pipe e i 40000 byte no?

Modificare:

Il processo di invio viene inviato un segnale SIGPIPE quando si tenta di scrivere su una pipe chiusa. Non so esattamente quando viene inviato il segnale, o quale effetto ha il buffer di tubi su questo. Potresti riuscire a recuperare intrappolando il segnale con la chiamata sigaction.