Modo corretto di gestire EINTR nelle librerie

6

Qual è l'etichetta consigliata quando si tratta di EINTR nelle librerie?

Attualmente sto scrivendo una funzione che fa alcune attività del file system con l'API POSIX, ma molte delle chiamate che uso possono potenzialmente restituire EINTR . Inoltre, la funzione può bloccare in alcune circostanze. (Per chi è interessato, implementa un meccanismo di blocco.)

Nell'interesse di renderlo il più generale possibile, vorrei sapere qual è il modo corretto per gestire una chiamata di sistema interrotta.

  • Dalla maggior parte delle fonti che ho letto, le persone tipicamente riprovano la chiamata e continuano la loro attività. Tuttavia, non sono sicuro che sia la cosa giusta da fare qui, dal momento che potrebbero esserci motivi legittimi per interrompere la mia funzione dato che può richiedere una notevole quantità di tempo. Inoltre, significa che EINTR verrebbe semplicemente ingoiato dalla funzione e il chiamante perderebbe qualsiasi indicazione che si sia verificato.

  • La mia strategia attuale consiste nell'annullare immediatamente l'operazione se ricevo EINTR e avvisare il chiamante. In questo modo, il chiamante può decidere se ritentare la mia funzione, giusto? (O forse la mia comprensione dei segnali è difettosa?)

posta Rufflewind 31.12.2014 - 15:17
fonte

1 risposta

4

Segnali in Unix

quando un altro processo invia il segnale di processo, il programma interromperà ciò che sta facendo ...

1) Esegui il codice del gestore che hai scritto. Non hai idea di cosa potrebbe fare il tuo programma quando arriva il segnale. Questa è l'idea con i segnali, possono essere completamente asincroni.

2) Quando il gestore del segnale è terminato, tipicamente fa solo un ritorno e il tuo programma continua da dove era stato interrotto, come se nulla fosse accaduto.

Trovate alcune informazioni utili in Richard Stevens

Una caratteristica dei precedenti sistemi UNIX è che se un processo ha catturato un segnale mentre il processo è stato bloccato in una chiamata di sistema "lenta", la chiamata di sistema è stata interrotta. La chiamata di sistema ha restituito un errore e errno è stato impostato su EINTR. Ciò è stato fatto ipotizzando che dal momento in cui si è verificato un segnale e che il processo sia stato rilevato, c'è una buona probabilità che qualcosa sia accaduto che dovrebbe riattivare la chiamata di sistema bloccata.

Semantica POSIX.1 per letture e scritture interrotte modificate con la versione 2001 dello standard. Versioni precedenti hanno dato alle implementazioni una scelta su come gestire le letture e le scritture che hanno elaborato quantità parziali di dati. Se read ha ricevuto e trasferito dati nel buffer di un'applicazione, ma non ha ancora ricevuto tutto ciò che l'applicazione richiede e viene quindi interrotto, il sistema operativo potrebbe non riuscire la chiamata di sistema con errno impostata su EINTR o consentire alla chiamata di sistema di riuscire, restituendo la quantità parziale di dati ricevuti. Allo stesso modo, se la scrittura viene interrotta dopo il trasferimento di alcuni dati nel buffer di un'applicazione, il sistema operativo potrebbe non riuscire la chiamata di sistema con errno impostata su EINTR o consentire alla chiamata di sistema di riuscire, restituendo la quantità parziale di dati scritti. Storicamente, le implementazioni derivate da System V falliscono la chiamata di sistema, mentre le implementazioni derivate da BSD restituiscono un parziale successo. Con la versione 2001 dello standard POSIX.1, sono richieste semantiche in stile BSD.

Il problema con le chiamate di sistema interrotte è che ora dobbiamo gestire esplicitamente il ritorno dell'errore. La tipica sequenza di codice (assumendo un'operazione di lettura e assumendo che vogliamo riavviare la lettura anche se è interrotta) sarebbe

again:
    if ((n = read(fd, buf, BUFFSIZE)) < 0) {
        if (errno == EINTR)
            goto again;     /* just an interrupted system call */
        /* handle other errors */
    }

Per impedire alle applicazioni di gestire chiamate di sistema interrotte, 4.2BSD ha introdotto il riavvio automatico di alcune chiamate di sistema interrotte.

    
risposta data 29.01.2015 - 11:25
fonte

Leggi altre domande sui tag