2013-02-15 2 views
5

Ich versuche, eine thread-sichere C-Protokollierungsfunktion zu schreiben, und ich habe einige schwerwiegende Probleme mit der Datei IO. Also, im Grunde beginne ich mit einem interessanten fopen Anruf, der mir das Protokoll in binären Update-Modus öffnen können:C: Sichere Thread-Protokollierung in eine Datei

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+"); 

Als nächstes Ich schließe die Datei, ein Timeout enthält, wenn ein anderer Thread Schlösser es zu lange:

//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); 
} 

und schließlich, ich hinzufügen, um die erforderliche Nachricht an das Ende der Datei, entsperren und schließen sie die Datei:

//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); 

jedoch scheint es, wie die Mehrheit des Chaos Alter wird im Protokoll überschrieben, anstatt angehängt, fast so, als ob einen "Schnappschuss" der Datei gemacht hätte, darauf gewartet hätte, dass sie entsperrt wird, und an das Ende der Datei geschrieben hat, wenn ein anderer Prozess nicht hinzugefügt wurde zu ihm. Hat jemand eine Idee, wie ich dieses Problem beheben könnte?

Als Nebenbemerkung möchte ich im binären Update-Modus sein, weil ich schließlich einige Funktionen zum Zuschneiden hinzufügen wird, die sicherstellen, dass die Protokolldatei eine bestimmte Größe nicht überschreitet, und dies ist einfacher für mich mit fseek aufrufen und R/W-Funktionalität.

Irgendwelche Tipps werden geschätzt. Danke im Voraus!

+0

Was passiert, wenn Sie mit einem Debugger durchgehen? – SecurityMatt

+0

Alle Ihre Operationen sind mit 'start' außer' fseek' und 'fwrite'. wird das erwartet? – Ganesh

+0

@Ganesh, Ja, ich wollte einen Dateizeiger an den Anfang der Datei halten und alles mit einem anderen machen, nur für den Fall, dass ich vor dem Entsperren einen 'rewind()' vergesse oder einen anderen Vorgang mache Zeiger auf den Anfang der Datei. – SuperTron

Antwort

5

Sie haben den Dateizeiger vor dem Entsperren nicht fflush() aufgerufen. Auf diese Weise blieb Ihre Log-Nachricht in einem Standardpuffer, der in fclose() zu einem Zeitpunkt ausgeschrieben werden kann, zu dem die Sperre nicht mehr gehalten wird.

Um das Problem zu beheben, fügen Sie vor dem Entsperren einen fflush(log) hinzu, oder verschieben Sie einfach den fclose(log) davor.

+2

Yup, das war es. Vielen Dank! – SuperTron