3

たまにタイマーを起動するシステムレベルのコードがあり、これらの信号が到着したときにそれらを管理する信号ハンドラーがあります。これは正常に機能し、完全に合理的なようです。メインプログラムと一緒に実行されている2つの別個のスレッドもありますが、それらは変数を共有しませんが、glibの非同期キューを使用してメッセージを一方向にのみ渡します。

同じコードでglibを使用しGHashTableて、キーと値のペアを格納しています。シグナルコードがシステムからコメントアウトされると、ハッシュテーブルは正常に動作しているように見えます。ただし、有効にすると、呼び出しが実際にNULLを返すという奇妙な競合状態が発生しg_hash_table_lookupます(つまり、検索に使用されたキーを持つエントリがないことを意味します)。実際にエントリが存在する場合(はい、確認しました)キーと値のペアのリスト全体をg_hash_table_foreach)で出力します。なぜこれがほとんどの場合に発生するのでしょうか?GLibのハッシュテーブルの実装はバグがありますか?ルックアップ呼び出しが成功する場合があります。

これは非常に特殊な状況であり、意味がない場合はさらに明確にすることができますが、これを実際に修正できるように、何か間違ったことをしていることを望んでいます。

詳細:シグナルハンドラスコープ内にないがg_hash_table変数にアクセスするコードセグメントは、シグナルブロッキング呼び出しに囲まれているため、プロセスが最初にこれらの変数にアクセスしていたときに、シグナルハンドラはこれらの変数にもアクセスしません。

4

1 に答える 1

3

一般に、シグナルハンドラーは、フラグを設定してシステムコールを実行することしかできません。

たまたま、ISO Cにはシグナルハンドラーが実行できることに関して厳しい制限があり、ほとんどのライブラリエントリポイントとほとんどのAPIはリモートで100%マルチスレッドセーフではなく、それらの約0.0%はシグナルハンドラーセーフです。つまり、シグナルハンドラからほとんどすべてのものを呼び出すことは絶対に禁止されています。

特に、GHashTableの場合、g_hash_table_ref()スレッドg_hash_table_unref()セーフでさえある唯一のAPI要素であり、シグナルハンドラーセーフではありません。実際、ISO-Cでは、シグナルハンドラで宣言されたオブジェクトvolatile sig_atomic_tのみを変更でき、2、3のライブラリルーチンのみを呼び出すことができます。

私たちの中には、スレッド化されたシステムを本質的に危険で、実際には放射性の微妙なバグの発生源であると考える人もいます。心配し始めるのに良い場所は、スレッドの問題です。(そして、シグナルハンドラー自体ははるかに悪いことに注意してください。APIが安全だとは誰も考えていません...)

于 2012-04-23T04:57:32.827 に答える