2

システムコールを中断するために、SIGALARM で sigsetjmp と singlongjmp の組み合わせを使用しています。これを次のコードに示します。

//data of Alarm_interrupter
void (TClass::*fpt)(const char*);   // pointer to member function
TClass* pt2Object;                  // pointer to object
===================================================
//for timeout processing
static sigjmp_buf jmpbuf;
static void recvfrom_alarm(int) {
    siglongjmp(jmpbuf, 1);
}
======================================================
void Alarm_interrupter::start_timeout() {
    signal(SIGALRM, recvfrom_alarm);
    alarm(timeout);
    (*pt2Object.*fpt)("timeouted before sigsetjmp"); //this call works OK
    if (sigsetjmp(jmpbuf,1) != 0) {
        //at this point, pt2Object is still OK,
        //but fpt seems to point to nothign.
        (*pt2Object.*fpt)("timeouted after sigsetjmp");
    }
    return;
}
==============================================================

sigsetjmp が 1 を返す前は、オブジェクトとメソッド ポインターを使用した呼び出し: *pt2Object.*fpt("timeouted before sigsetjmp") は問題ありませんが、sigsetjmp が 1 を返した後、この呼び出しは失敗しました。変数の状態を調べたところ、オブジェクト ポインター "pt2Object" はまだ問題ありませんが、メソッド ポインター "fpt" は異なるようです。

考えられる理由の 1 つは、sigsetjmp がメソッド ポインター「fpt」を含む以前の環境全体を復元できないことです。

この問題を解決するのを手伝ってくれませんか。本当にありがとう!

4

1 に答える 1

1

Potatoswatter が指摘しているように、アラームを使って時間を遅らせるのlongjmpは賢明すぎて頼りになりません。最初に「sigsetjmp」を呼び出す必要があります。そこに戻ろうとする前に、それが起こらなければなりません。

唯一の方法sigsetjmpまたはsetjmp機能する方法は、この擬似コードに従うことです。

if (sigsetjmp(...) != 0) {
    //  Error handling code
}
// code that might call siglongjmp to bail out to Error handling code

ご覧のとおり、コンテキストの保存を実行するには、一度実行する必要があります。これにより、 が初期化されますjmpbuflongjmp実行の早い段階で呼び出しを行わずに呼び出した場合setjmp、動作は予測できません。

また、longjmp使用しようとする可能性のあるローカル変数を消去する傾向があります。

int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // could print 2, 3 or even "potato". Local vars get trashed.
}
// code that might call siglongjmp to bail out to Error handling code

だから、あなたは本当にすべての興味深いことをしたいと思っています*setjmp.

int var = 3;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    var = 2;
    printf("%d", var); // now you know it's 2
}
// code that might call siglongjmp to bail out to Error handling code

. _ *longjmp_volatile

volatile int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code

そして、これでも十分ではないかもしれません。sigatomic_t などと呼ばれるものが必要になる場合があります。しかし、そのようなクレイジーなものを必要としないようにしてください.

int var = 3;
memcpy(var, (int *){2}); //memcpy is pretty reliable (C99ism: immediate pointer))
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code
于 2013-03-07T04:37:08.573 に答える