2013-02-15 17 views
5

Sto tentando di scrivere una funzione di registrazione C thread-safe e sto riscontrando alcuni problemi gravi con il file IO. Quindi, in sostanza, comincio con un interessante fopen chiamata che mi permette di aprire il registro in modalità di aggiornamento binario:C: registrazione sicura del thread in un file

FILE *log, *start; 
int timeout = 0, error; 

//make file (fails if file exists) 
log = fopen(LOG_FILE, "wx"); 

//Close the file if a new one was created 
if(log) 
    fclose(log); 

//Open file in update mode (it must exist for this) 
log = fopen(LOG_FILE, "rb+"); 

Avanti, chiudo il file, che incorpora un timeout se un altro thread serrature per troppo tempo:

//Init other file pointer 
start = log; 

//Lock file (with timeout) 
rewind(start); 
error = lockf(fileno(start), F_TLOCK, 0); 
while(error == EACCES || error == EAGAIN) 
{ 
    //sleep for a bit 
    usleep(LOCKED_FILE_RETRY_TIME); 

    //Incremement timeout 
    timeout += LOCKED_FILE_RETRY_TIME; 

    //Check for time out 
    if(timeout > LOCKED_FILE_TIMEOUT) 
    { 
    return; 
    } 

    //Retry the lock operation 
    error = lockf(fileno(start), F_TLOCK, 0); 
} 

e, infine, aggiungo il messaggio richiesto alla fine del file, sbloccarlo e chiudere il file:

//Print log entry 
fseek(log, 0, SEEK_END); 
fwrite((const void*) log_msg, 1, strlen(log_msg), log); 

//Unlock the block 
rewind(start); 
lockf(fileno(start), F_ULOCK, 0); 

//Close file 
fclose(log); 

Tuttavia, sembra che la maggior parte del caos le età vengono sovrascritte nel registro, anziché accodate, quasi come se lo fopen prendesse una "istantanea" del file, attendesse che venisse sbloccata e scrivesse dove sarebbe stata la fine del file se un altro processo non aggiungeva ad esso. Qualcuno ha qualche idea su come posso risolvere il problema?

Come parte, voglio essere in modalità di aggiornamento binario perché alla fine aggiungerò alcune funzionalità di rifilatura che garantiranno che il file di registro non superi una determinata dimensione, e questo è più facile per me realizzare con chiamate fseek chiamate e Funzionalità R/W.

Qualsiasi consiglio è apprezzato. Grazie in anticipo!

+0

Cosa succede quando si passa con un debugger? – SecurityMatt

+0

Tutte le operazioni sono con 'start' tranne' fseek' e 'fwrite'. è previsto? – Ganesh

+0

@Ganesh, Sì, volevo mantenere un puntatore del file all'inizio del file e scrivere tutto con un altro, nel caso mi fossi dimenticato di fare 'rewind()' prima di sbloccare o eseguire un'altra operazione che richiede un puntatore all'inizio del file. – SuperTron

risposta

5

Non hai chiamato fflush() sul puntatore del file prima di sbloccare. In questo modo il tuo messaggio di registro è rimasto in un buffer stdio, da scrivere in fclose(), in un momento in cui il blocco non viene più trattenuto.

Per risolvere il problema, aggiungere uno fflush(log) prima dell'operazione di sblocco o semplicemente spostare lo fclose(log) prima di esso.

+2

Sì, è quello che era. Grazie! – SuperTron

Problemi correlati