8

次のsigactionハンドラー関数があります

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

誰かが私に言った、flockそしてprintf非同期シグナルセーフではありません。flockそして、このリストには代替の async-signal-safe 関数が見つかりませんでした 。

上記のリンクによると:

シグナルが安全でない関数に割り込み、シグナルをキャッチする関数が安全でない関数を呼び出す場合、動作は未定義です。

flock async-signal-safeにする方法はありますか? flockまたは、信号を受信したときに実行する別のソリューションはありTERMますか?

4

3 に答える 3

4

flock()システムコールであるため、一般的に非同期シグナルセーフです。そのセマンティクスにより、別の方法で実装することが困難になります。POSIX にまったく含まれていないため、POSIX の async-signal-safe 関数のリストには含まれていません。

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

printf()とのfprintf()呼び出しは、適切な呼び出しに置き換える必要がありwrite()ます。stdio 関数は、async-signal-safe 関数のリストに含まれておらず、多くの場合、async-signal-unsafe です。

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

于 2013-06-06T21:21:36.273 に答える
4

flock() の代わりにfcntl()を使用できます。

于 2013-06-06T17:12:02.683 に答える
0

exit()シグナル ハンドラーの代わりに使用し、 atexit()abort()を使用して、安全でない関数を終了ハンドラーに入れることができます。

更新:一般に、潜在的にブロックするシステム コールをシグナル ハンドラに配置しないでください。これを回避する 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;
}
于 2013-06-06T17:06:15.327 に答える