web-dev-qa-db-ja.com

straceとltraceがEINTRを引き起こすのはなぜですか?

このプログラムを検討してください。

#include <stdio.h>
#include <sys/epoll.h>

int main(void) {
       int epfd = epoll_create1(0);
       struct epoll_event event;
       event.events = EPOLLIN;
       event.data.fd = 0;
       epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event);
       epoll_wait(epfd, &event, 1, -1);
       perror("epoll_wait");
       return 0;
}

このプログラムを単独で実行すると、端末のサイズを変更しても(つまり、SIGWINCHが生成されても)何も実行されず、stdinでの入力を待機し続けます。 straceまたはltrace内で実行すると、SIGWINCHによってepoll_waitがEINTRでエラーになります。 EINTRについての私の理解は、シグナルがコード内のシグナルハンドラーを呼び出す場合にのみ生成されるということですが、それらのいずれも登録されていません。 straceまたはltraceが設定しているのではないかと思ったので、明示的にSIG_IGNに設定してみましたが、それでもEINTRは停止しませんでした。なんでこんなことが起こっているの?

彼らはptrace(2)を使用し、そのマニュアルページのコメント

トレース中は、シグナルが配信されるたびにトレーシーが停止します。シグナルが無視されている場合でも。 (例外はSIGKILLで、通常の効果があります。)トレーサーは、次のwaitpid(2)((または関連する「待機」システムコールの1つ)。その呼び出しは、トレースの停止の原因を示す情報を含むステータス値を返します。トレーシーが停止している間、トレーサーはさまざまなptrace要求を使用して、トレーシーを検査および変更できます。次に、トレーサーはトレーシーを続行させ、オプションで配信された信号を無視します(または代わりに別の信号を配信します)。

以降:

抑制された信号は、システムコールが時期尚早に戻る原因となることに注意してください。この場合、システムコールが再開されます。トレーサーはトレーシーを監視して、中断されたシステムコールを再実行します(またはrestart_syscall(2)異なるメカニズムを使用するいくつかのシステムコールのシステムコール再起動用)トレーサーが_PTRACE_SYSCALL_を使用する場合。シグナルが抑制された後にシグナルが再始動された後に再始動できないシステムコール(poll(2)など)でさえ。 ただし、トレースに観測可能な信号が注入されていなくても、一部のシステムコールがEINTRで失敗するカーネルバグが存在します

デフォルトでは、SIGWINCHは無視されますが、epollpollと十分に類似しており、EINTRが表示されているように聞こえます。発信者に(再起動しても)。

3
Thomas Dickey