2013-06-06 29 views
6

は私が関数を非同期シグナル安全にするには?

void signal_term_handler(int sig) 
{ 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
    abort(); 
} 

sigactionハンドラ関数を持っている人はflockprintfは、非同期シグナルセーフではありませんと言ってくれました。そして、私はこのlistflockの代替非同期シグナルセーフ機能を見つけることができませんでした。

して上記のリンクによるとは:

信号が安全機能と信号を引く 機能は危険な関数を呼び出しを中断し、動作が

は仕方あります定義されていませんflock async-signal-safeを作るには?それとも私がTERM信号を受信したときflockを実行するための別の解決策はありますか?

+0

の可能性のある重複した[シグナルハンドラ内でのprintfを使用して回避する方法?](https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler)について'flock'ため' printf'、https://stackoverflow.com/questions/16979059/use-flock-in-the-sigaction-handler。 –

答えて

4

flock()の代わりにfcntl()を使用できます。それはシステムコールであるため、

+0

'fcntl()'ロックの意味は 'flock()'のものと異なり、それほど有用ではないことに注意してください。 – jilles

+0

実際、私はfcntlを使って、この[topic](http://stackoverflow.com/questions/16988256/how-to-lock-and-unlock-pid-file-news)で示されているように新しいプロパティのflock()関数を開発することができます。 with-fcntl)。回答ありがとうございました – MOHAMED

0

あなたのシグナルハンドラに代わり abort()exit()を使用して、 atexit()を使用して終了ハンドラにあなたの危険な関数を置くことができます。

更新:通常、シグナルハンドラに潜在的にブロックしているシステムコールを入れないでください。これを避ける方法の1つは、シグナルハンドラにフラグを設定し、メインループのコンテキストで必要な機能を実行することです。

volatile int shutdown = 0; 

void signal_term_handler(int sig) 
{ 
    shutdown = 1; 
} 

void cleanup() { 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
} 

void *workerFunction(void *arg) { 
    while (!shutdown) { 
     ... do stuff ... 
    } 
    return NULL; 
} 

int main(int argc, char *argv[]) { 
    //... 
    pthread_create(...,workerFunction,...); 
    pthread_join(...); 
    cleanup(); 
    return 0; 
} 
+0

出口ハンドラは同期的に呼び出すことができます。非同期的に呼び出されるシグナルハンドラからそのようにすると、どのように実行されるのですか? – alk

+0

そうですね、慎重に質問を読んでいませんでした。シグナルハンドラで安全でない関数を避ける方法について、もっと基本的な質問に答えていたと思います。この場合、exit()をシャットダウンフラグを設定するようなものに置き換えることをお勧めします。 –

+0

これは間違っています。それは揮発性でなければなりませんsig_atomic_t –

4

flock()は、一般的に非同期シグナルセーフです。そのセマンティクスは、それを別々に実装するのを難しくします。これは、POSIXのPOSIXにはないため、POSIXの非同期シグナル安全関数のリストにはありません。

開いているファイルの説明を参照するすべてのファイル記述子が閉じられると、flock()ロックが自動的に解放されるため、明示的なロック解除は必要ありません。

printf()fprintf()コールは、適切なwrite()コールで置き換える必要があります。 stdio関数は非同期シグナル安全関数のリストにはなく、しばしば非同期シグナルが安全でないことが多い。

abort()コールは、おそらく最高のデフォルトのアクションに信号を設定し、自己にそれを再送信することで置き換えられます。このように、シェルはシグナルのためにあなたのプログラムが終了したことを知り、必要に応じてコマンドシーケンスを中止することができます。

+0

sigactionハンドラで問題なく 'flock()'を使用できますか? – MOHAMED

+0

はい、私が言ったように、あなたがする必要はないかもしれません。 – jilles

関連する問題