2013-02-15 54 views
5

मैं थ्रेड-सुरक्षित सी लॉगिंग फ़ंक्शन लिखने की कोशिश कर रहा हूं, और मुझे फ़ाइल IO के साथ कुछ गंभीर समस्याएं आ रही हैं। तो, मूल रूप से, मैं एक दिलचस्प fopen कॉल मुझे द्विआधारी अद्यतन मोड में लॉग खोलने देता है के साथ शुरू:सी: एक फ़ाइल में थ्रेड सुरक्षित लॉगिंग

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

इसके बाद, मैं फ़ाइल ताला, एक टाइमआउट को शामिल करता है, तो लंबे समय के लिए एक और धागा ताले यह:

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

और अंत में, मैं फ़ाइल के अंत करने के लिए आवश्यक संदेश जोड़ने के लिए, इसे अनलॉक और फ़ाइल को बंद करें:

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

हालांकि, यह गंदगी के बहुमत की तरह लगता है उम्र में उम्र को अधिलेखित करने के बजाए लॉग में ओवरराइट किया गया है, लगभग fopen ने फ़ाइल का "स्नैपशॉट" लिया, इसे अनलॉक करने के लिए इंतजार किया, और लिखा कि फाइल का अंत क्या होगा यदि कोई अन्य प्रक्रिया नहीं जुड़ी इसके लिए क्या किसी को इस बारे में कोई विचार है कि मैं इस समस्या को ठीक करने के बारे में कैसे जा सकता हूं?

एक तरफ, मैं बाइनरी अपडेट मोड में होना चाहता हूं क्योंकि मैं अंततः कुछ ट्रिमिंग कार्यक्षमता जोड़ूंगा जो सुनिश्चित करेगा कि लॉग फ़ाइल एक निश्चित आकार से अधिक न हो, और मेरे लिए यह काम करना आसान है fseek कॉल और आर/डब्ल्यू कार्यक्षमता।

किसी भी सुझाव की सराहना की जाती है। धन्यवाद पहले से ही!

+0

जब आप डीबगर के साथ कदम उठाते हैं तो क्या होता है? – SecurityMatt

+0

आपके सभी ऑपरेशन 'fseek' और' fwrite' को छोड़कर 'स्टार्ट' के साथ हैं। क्या यह उम्मीद है? – Ganesh

+0

@ गणेश, हां, मैं फ़ाइल की शुरुआत में एक फ़ाइल पॉइंटर रखना चाहता था और मेरे सभी लेखन को एक और के साथ करना चाहता था, बस अगर मैं अनलॉक करने या किसी अन्य ऑपरेशन करने से पहले 'रिवाइंड()' करना भूल गया था फ़ाइल की शुरुआत के लिए सूचक। – SuperTron

उत्तर

5

आपने अनलॉक करने से पहले फ़ाइल पॉइंटर पर fflush() पर कॉल नहीं किया था। इस तरह आपका लॉग संदेश stdio बफर में रहा, जिसे fclose() में लिखा जाना चाहिए, जब लॉक अब नहीं चल रहा है।

समस्या को ठीक करने के लिए, या तो अनलॉक ऑपरेशन से पहले fflush(log) जोड़ें, या बस इससे पहले fclose(log) को स्थानांतरित करें।

+2

यूप, यही वह था। धन्यवाद! – SuperTron