シグナルハンドラーで非同期セーフでない関数を呼び出せるかどうかを調べています。
Linux の man ページからの引用 signal(7):
シグナルが安全でない関数の実行を中断し、ハンドラが安全でない関数を呼び出す場合、プログラムの動作はundefinedです。
とTLPI :
SUSv3 は、表 21-1 (非同期セーフ関数のリスト) にリストされていないすべての関数は、シグナルに関して安全でないと見なされることを指摘していますが、関数が安全でないのは、シグナル ハンドラの呼び出しが関数の実行を中断する場合のみであると指摘しています。安全でない関数、およびハンドラー自体も安全でない関数を呼び出します。
上記の引用の私の解釈は、シグナルハンドラーが非同期セーフでない関数を中断しなかった場合にのみ、シグナルハンドラーから非同期セーフでない関数を呼び出すことが安全であるということです。
たとえば、安全でない関数を呼び出す SIGINT のハンドラーをインストールしますcrypt(3)
。これは、再入不可、つまり安全ではないと思われます。
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);
またprintf()
、 で無限ループを呼び出しmain()
、メイン スレッドのみを実行しています。
printf()
問題は、この単純な例に対するものです。ハンドラーが実行を中断し、安全でない関数を呼び出したときに、悪いことが起こることはありません。AFAK はprintf()
、コンソール ロックを取得し、バッファリングされた I/O を実行するための内部バッファを持っていますが、この例ではその状態は一貫しています。静的に割り当てられた文字列を返しますがcrypt()
、他の関数やスレッドとは共有されません。
私は何か誤解していますか?シグナルハンドラがメインプログラムの安全でない関数の実行を中断し、それ自体も安全でない関数を呼び出すことは常に安全ではないこと、または状況によっては安全であるということを誰かに明確にしてもらいたい(例: 上記の単純な例) ?