Voglio solo sapere qual è il comportamento di avere due chiusure consecutive su una fd.È possibile effettuare più chiamate chiuse per un fd con la stessa funzione?
e.g.-
close(fd);
close(fd);
[fd è un int]
Voglio solo sapere qual è il comportamento di avere due chiusure consecutive su una fd.È possibile effettuare più chiamate chiuse per un fd con la stessa funzione?
e.g.-
close(fd);
close(fd);
[fd è un int]
Il la prima chiamata dovrebbe restituire 0
; la seconda chiamata deve restituire -1
e impostare errno
su EBADF
.
È necessario impedire che la seconda chiamata accada impostando fd
a un numero errato noto, ad es. un -1
subito dopo la prima chiamata di close
, e successivamente il controllo fd
prima di effettuare la seconda chiamata (e non effettuare la chiamata se fd
è -1
):
close(fd);
fd = -1;
...
// More code
...
if (fd != -1) {
close(fd)
fd = -1;
}
Questo modello di codice vi aiuterà quando è necessario effettuare chiamate verso close
da più posizioni, ma non si è sicuri se il file è aperto o se è già stato chiuso. Passare da -1
a close
è innocuo (si otterrebbe uno EBADF
, ovviamente).
Dovrebbe essere innocuo a meno che non si sta filettata o fare qualcosa fra le due chiamate di chiudere. Quindi potresti finire per chiudere un file che è stato aperto da qualcos'altro nel tuo programma.
Il modo in cui il threading è rilevante è che le librerie quasi sempre fanno cose strane alle vostre spalle. Libc aprirà i file per cercare i messaggi di errore o altre cose dipendenti dalla localizzazione, il resolver può aprire i file di configurazione, ecc. Se chiudi un descrittore di file e lo chiudi di nuovo, in un ambiente con thread puoi facilmente finire in una situazione in cui il file il descrittore è stato riutilizzato da una biblioteca e lo si chiude dietro la schiena.
+1 per menzionare possibili problemi in un ambiente con thread. – alk
La * prima * chiamata alla chiusura potrebbe chiudere un file da un altro thread. Due chiusure non sono rilevanti per quel problema. L'unico modo in cui il threading è rilevante qui è che il secondo potrebbe non fallire dopo tutto se quel file fd è stato riaperto, ma non è interessante ... se non sincronizzi i tuoi thread possono accadere tutti i tipi di cose brutte. –
Il valore restituito da 'open()' viene riciclato dal sistema operativo. Quindi se il thread A ha chiamato 'open()' e ha ottenuto fd = 3, quindi 'close() è s. Quindi, poco prima che il thread A chiamasse 'close()' la seconda volta, il thread B ha chiamato 'open()' con successo e ha ottenuto fd = 3 di nuovo. Quindi quale sarebbe il secondo 'close()' chiamato dal thread A do? – alk
Se il fd valore di pf rimane lo stesso la seconda chiamata restituirà un errore che il fd non è valido (EBADF - come dasblinkenlight sottolineato)
pensare di fare quacosa likg
if fd != -1)
{
close (fd);
fd = -1;
}
Questo tipo di cose non ha senso, poiché close (fd) non è indefinito o comunque pericoloso quando fd è già chiuso ... close (fd) e close (-1) fanno esattamente la stessa cosa. L'unica ragione per impostare fd su -1 è assicurarsi che non sia un descrittore di file aperto valido come 0. –
Ok, la gente ha notato che un descrittore di file potrebbe essere stato riaperto in un altro thread, quindi impostando fd = -1 è una buona pratica. Ma il test 'fd! = -1' non è strettamente necessario ... l'effetto è lo stesso senza di esso. –
Sono d'accordo con te che il test per -1 non è necessario. Ancor più: in un debug-build lo ometterei, e registro l'errore 'close()' tornerebbe quindi, per indicarmi il casino che ho creato che porta a provare a chiudere il file due volte ... ;-) @ JimBalter – alk
La seconda chiamata avrà esito negativo con Errno: EBADF
quando perché, a questo punto, fd non è un descrittore di file attivo.
Non dovrebbe avere alcun effetto sull'esecuzione. Tuttavia, se un numero di errore è stato impostato dalla prima chiusura, questo andrà perso, quindi non si dovrebbe chiudere due volte il descrittore di file.
Ah, questa risposta dice in realtà qualcosa di valido! +1 –
Chiusura del stessa FD due volte dovrebbe essere non-fatale, come altri hanno fatto notare, ma attenzione di codice come questo
close(fd);
/* ... */
newfd = open(....);
/* ... */
close(fd);
Con il secondo vicino, non si può essere sicuri se è in realtà fd
lo stesso di newfd
! Ciò porterebbe a crash ogni volta che si tenta di utilizzare newfd
.
Quindi (se c'è il codice tra le due chiamate close
) non è sicuro farlo. Sempre i descrittori di file close
esattamente una volta.Sempre i buffer free
esattamente una volta.
Perché dovresti evitare che la seconda chiamata accada? –
Impostare fd su -1 non ha alcun effetto (certamente non "impedisce che la seconda chiamata accada") ... sia quella che una fd chiusa rendimento EBADF –
@JimBalter impostando da fd a -1 si eviterebbe il rischio di chiudere occasionalmente un file un altro thread appena aperto. – simonc