2013-08-19 6 views
6

Alcuni mesi fa scrivo un'applicazione CGI per Linux che utilizza popen() per leggere l'output di un comando, quindi chiudo la pipa con fclose().usare fclose to pipe of popen è un bug serio?

Ora, ho letto che per tubi stretti è necessario utilizzare pclose().

Il manuale dice:

Il valore restituito da popen() è un flusso normale standard di I/O in tutti gli aspetti salvo che esso deve essere chiuso con pclose() piuttosto che fclose(3).

Il mio codice è simile a questo:

if ((NULL != (f = popen(command.value, "r")))) { 
    //do something 
    fclose(f); 
} 

La mia domanda è:

Il mio errore ha un problema di sicurezza? Il programma è attualmente in produzione. Nei test non fa niente. E 'davvero necessario, patch usando invece fclose()? Nota: apro il PIPE solo una volta nel programma.

Oggi, nella mia casa locale faccio un po 'di test e fclose() e pclose() non tornare EOF che indica il fallimento.

+2

Hai comportamento indefinito : Leggi ['pclose()' vs 'fclose()'?] (Http://cboard.cprogramming.com/cplusplus-programming/97147-pclose-vs-fclose.html): La funzione '_pclose' cerca il ID di processo del processore di comandi (CMD.EXE) avviato dalla chiamata '_popen' associata, esegue una chiamata' _cwait' sul nuovo processore di comandi e chiude lo stream sulla pipe associata. –

+0

Ci sono alcuni post SO relativi alla tua domanda: 1. ['fclose ()/pclose() 'può bloccare su alcuni puntatori di file] (http://stackoverflow.com/questions/1736983/fclose-pclose-may-block-on-some-file-pointers) e [Come chiudere il pipe handle in unix ? '(fclose() di pclose())'?] (http://stackoverflow.com/questions/5548364/how-close-pipe-handle-in-unix-fclose-of-pclose) –

+0

grazie, correggerò perché è veramente importante Ora, sembro l'impatto. – carlos

risposta

5

Se si utilizza fclose sulla pipe, si avranno perdite di descrittori di file, poiché fclose non libererà il puntatore del file nel kernel (che viene creato quando si crea la pipe dal momento che è un file).

Mentre i test finora non hanno mostrato problemi, esegui il tuo programma 3000 volte (o come mai molti descrittori di file sono consentiti, verso l'alto di un int credo) e guarda quando non sarai più in grado di creare pipe .

+2

In genere 'fclose' sul flusso stdio in realtà * fa * chiude il descrittore di pipe sottostante (è nascosto in' fp -> _ fileno' o qualunque sia il nome del campo), quindi è più una perdita di zombie-proc di una perdita di fd. – torek

10

Secondo this thread, utilizzando fclose anziché pclose significa che il processo all'altra estremità del tubo non viene raccolto, così rimane zombied.

+0

molto grazie, quindi non sto chiudendo la pipa, è brutto, grazie. – carlos

0

Ho appena scoperto (dopo 10 anni) che stavo usando erroneamente fclose per alcune chiamate popen, in esecuzione sul server Windows 2008. Ha funzionato (cioè non si è bloccato), e non mi importava del codice di ritorno su quelle chiamate comunque.

Ma avevo bisogno del codice di ritorno dell'ultimo flusso popen e la chiusura è stata eseguita correttamente con pclose.

Ha lo strano effetto di restituire un codice di 0 errore (forse raccogliendo il codice di ritorno della prima non pclosed processo), anche se il comando non è riuscito, creando uno strano bug nel codice, che avrebbero potuto portare a errori catastrofici perché il chiamante pensa che il comando ha funzionato.

Quindi non è solo una questione di descrittori perdite, si può introdurre bug funzionali nel codice, (anche se l'applicazione viene eseguita per alcuni secondi e non si preoccupano di descrittori perdite)

+0

BTW, è molto specifico del sistema operativo. L'OP ha chiesto esplicitamente su Linux. E le solite distribuzioni Linux hanno libc software libero, quindi l'OP dovrebbe studiare il codice sorgente della sua particolare implementazione di libc. –

+0

ok, ma quello che è successo per me su Windows potrebbe accadere anche su altri sistemi. –

+0

Tranne che l'aspetto del software libero sta cambiando molto su come risolvere quel problema. Se la tua libc (e il suo kernel) era un software libero, puoi esaminare e studiare il suo codice sorgente (e capire cosa succede). –