2013-02-15 15 views
5

スレッドセーフなCのログ機能を記述しようとしていますが、ファイルIOに重大な問題があります。だから、基本的に、私は私がバイナリアップデートモードでログを開くことができます面白いfopen呼び出しで起動します。C:ファイルへのスレッドセーフのログ

を:

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コールとR/W機能。

ご了承ください。あらかじめありがとう!

+0

デバッガをステップ実行するとどうなりますか? – SecurityMatt

+0

あなたのすべての操作は 'fseek'と' fwrite'を除いて 'start'です。これは期待ですか? – Ganesh

+0

@Ganesh、はい、ファイルの先頭に1つのファイルポインタを置いて、別のものですべての書き込みを行いたいのですが、ロックを解除する前に 'rewind()'を実行するのを忘れた場合や、ファイルの先頭へのポインタ。 – SuperTron

答えて

5

ロックを解除する前にファイルポインタにfflush()を呼び出していませんでした。そうすれば、あなたのログメッセージは、ロックがもはや保持されていないときに、fclose()に書かれたstdioバッファに残ったままです。

問題を解決するには、ロック解除操作の前にfflush(log)を追加するか、単にその前にfclose(log)を移動してください。

+2

うん、それはそうだった。ありがとう! – SuperTron

関連する問題