2013-02-15 20 views
5

Bir iş parçacığı güvenli C günlüğe kaydetme işlevi yazmaya çalışıyorum ve IO dosyasıyla bazı ciddi sorunlar yaşıyorum. Yani temel olarak bana ikili güncelleme modunda kaydını açmak sağlayan ilginç bir fopen çağrısı ile başlar:C: Bir Dosya için Güvenli Oturum Açma

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

Sonraki, bir zaman aşımı içeren dosyayı kilitlemek eğer çok uzun süre başka bir iş parçacığı kilitler:

o karmaşa çoğunluğu gibi görünüyor, ancak

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

:

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

ve son olarak, dosyanın sonuna için gerekli mesaj eklemek, kilidini ve dosyayı kapatın Çağlar, günlüğe eklenmek yerine, imlecin üzerine yazılır, neredeyse sanki fopen dosyanın "anlık görüntüsünü" aldı, kilidi açılmasını bekledi ve başka bir işlem eklenmediyse dosyanın sonuna nerede yazılacağını yazdı ona. Bu sorunu düzeltmek için nasıl gidebileceğimi bilen var mı?

Bir kenara göre ikili güncelleme modunda olmak istiyorum çünkü sonuçta, günlük dosyasının belirli bir boyutu aşmamasını sağlayacak bazı düzeltme işlevlerini ekleyeceğim ve bu, fseek çağrıları ile çalışmam için daha kolay ve R/W işlevselliği.

Herhangi bir ipucu takdir edilmektedir. Şimdiden teşekkürler!

+0

Hata ayıklayıcısına geçtiğinizde ne olur? – SecurityMatt

+0

Tüm işlemleriniz 'fseek' ve' fwrite' haricinde 'start' ile yapılır. bu beklenen mi? – Ganesh

+0

@Ganesh, Evet, bir dosya tanıtıcısını dosyanın başlangıcında tutmak istedim ve tüm yazımı bir başkasıyla yapmak istedim, sadece bir 'rewind() 'un kilidini açmadan önce veya bir başka Dosyanın başlangıcına işaretçi. – SuperTron

cevap

5

Kilit açmadan önce dosya tanıtıcısında fflush()'u aramadınız. Bu şekilde günlük mesajınız, kilitlenmediği bir zamanda fclose()'da yazılan bir stdio tamponunda kalmıştır.

sorunu çözmek ya kilidini ameliyattan önce bir fflush(log) eklemek veya sadece ondan önce fclose(log) taşıyın.

+2

Yup, işte böyle oldu. Teşekkürler! – SuperTron