7

問題を引き起こした巨大なファイバー スケジューラ コードを以下の行にまとめました。
私が期待しているのは、毎回ハンドラーに渡されたコンテキストへのクリーンなリターンです。
私が得るのは "Handler." で、3 回出力された後、セグメンテーション違反が発生します。

#include <ucontext.h>
#include <signal.h>
#include <stdio.h>

ucontext_t currently_executed_context;

void handler_sigusr1(int signum, siginfo_t* siginfo, void* context)
{
    currently_executed_context = (*(ucontext_t*)context);

    printf("Handler. ");
    setcontext(&currently_executed_context);
}

int main()
{
    setbuf(stdout,0);

    struct sigaction action_handler;

    action_handler.sa_sigaction = handler_sigusr1;
    action_handler.sa_flags = SA_SIGINFO;

    sigaction(SIGUSR1,&action_handler,NULL);

    for(;;) { kill(getpid(),SIGUSR1); sleep(1); }

    return 0;
}

2 つの異なる Linux ディストリビューションで gcc-4.4.3 と gcc-4.4.5 の両方を使用しました。

4

1 に答える 1

1

この時点で、問題に関する私自身の調査が部分的な回答として提供されます。

まず、この記事を見つけました。これは古く、公式の情報源を引用していません: http://zwillow.blogspot.com/2007/04/linux-signal-handling-is-broken.html。これは関連する引用です:

2 番目の問題: setcontext() を使用してシグナル ハンドラを終了し、以前に保存された別のコンテキストにジャンプすることはできません。(あるいは、それを使用して、シグナル ハンドラーに引数として渡されたものとまったく同じコンテキストに戻ることはできません。) つまり、次のようなシグナル ハンドラー

static void sighandler(
   int signo, siginfo_t *psi, void *pv)
{
  memcpy(puc_old, pv, sizeof(ucontext_t));
  /* choose another context to dispatch */
  setcontext(puc_another);
}

動作しません。puc_other で指定されたシグナル マスクを復元したり、代替シグナル スタックを再確立したりしません。ただし、このスキームは Solaris では問題なく動作します。

どなたかSolarisの部分を確認していただけると助かります。

第二に、大学の講師と話した後、シグナルハンドラーからコンテキストを設定/交換することは、他の状況で行うほど簡単ではないことを理解するようになりました。悲しいことに、これを私に説明してくれた人は、その時点でそれ以上の詳細を提供できませんでした.

したがって、私の情報源はどちらも完全に信頼できるとは思えませんが、それでも手がかりにはなります。

于 2013-03-29T22:01:12.857 に答える