5499

[code]

    struct sigaction sa;
    sa.sa_flags = SA_RESTART;
    
[/code]

というように、シグナルのフラグとしてSA_RESTARTというのがあります。

私の理解では、「SA_RESTARTを設定している場合、recv()などの実行文においてシグナルを受けてもrecv()から抜け出さず、受けたシグナルの処理する」という理解です。

実際のソフトを作る場合、SA_RESTARTは設定する/しない、どちらでよく使われるものでしょうか?

SA_RESTARTを設定していると、意図しないrecv()からの抜け出しがなくなりよさそうに思うのですが、そうなのでしょうか？


CC BY-SA 3.0
2015-01-28T01:09:05.243
5469
2015-01-29T02:29:52.770
4840
question
linux c
linux application > signal > SA_RESTARTの使いどころ


シグナルがハンドラにより処理された **後** に、recv()などのシステムコールからEINTRで抜けるか、自動的に再試行するかを決めるフラグですね。

使うかどうかは目的によるとしか言えないと思います。使わない場合、システムコールがエラーを返したらerrnoがEINTRかどうかを調べて、そうなら再試行する、というコードを自分で書くことになります。私はある程度の規模ならそのパターンをマクロなどで隠蔽してしまいますが、そのへんはプロジェクトのポリシーに依存するでしょう。

ただ、自動的再試行が起きるかどうかには色々条件があります。どのシステムコールか、またどのデバイスに対して読み書きしているかにも影響されます。詳しくは[signal(7)](http://man7.org/linux/man-
pages/man7/signal.7.html)を参照。  
さらに、既にある程度のデータが読み書きされていた場合はSA_RESTARTがあっても再試行はされずシステムコールは成功を返します。

また、昔ひっかかったことがあるのですが、sleep系コール(sleep, nanosleep,
usleep等)も自動再起動されません。ここで10秒休んでるはず、と思ってるのが頻繁にシグナルを受けてて実は全然休んでいなかった、なんてことがありました。

従って、「確実にnバイト書き込みたい/読み出したい」とか「確実にn秒ウェイトしたい」といった場合はSA_RESTARTを使おうが使うまいが返り値を調べてループすることになるので、使い勝手はそれほど良くない機能だな、というのが個人的な印象です。


CC BY-SA 3.0
2015-01-28T06:50:59.283
5499
2015-01-28T06:50:59.283
5258
5469
answer


（直接の回答ではありませんが、関連情報の提供として）

<http://www.oki-osk.jp/esc/linux/signal-6.html> では、`SA_RESTART`
指定が適切でない状況を説明しています。（シグナル`SIGALRM`によるタイムアウト実装）

> 6.1.2 signal 関数の真実  
>  現行の Linux (すなわち GNU/Linux) の glibc 標準ライブラリは signal(2) を BSD UNIX
> 互換のライブラリ実装にすげ替えている。 すなわち，`signal` 関数を sigaction(2) で `sa_flags` メンバに
>
> `SA_RESTART`
>
> を与えた場合と等価であるように定義している。
>
> `SA_RESTART` オプションを与えた場合，シグナルを受けた各システム・コールはシグナルで打ち切られた処理を内部で自動的に再開 (restart)
> する。 本章のプログラム例でいえば，制限時間の 10 秒がたっても read(2) はそのまま入力待ちを続けることになる。
> しかし，これは意図したことではない。


CC BY-SA 3.0
2015-01-29T02:29:52.770
5547
2015-01-29T02:29:52.770
49
5469
answer