siglongjmp() - スタック環境とシグナル・マスクの復元

標準

標準/拡張機能 C/C++ 依存項目

POSIX.1
XPG4
XPG4.2
Single UNIX Specification、バージョン 3

両方  

形式

#define _POSIX_SOURCE
#include <setjmp.h>

void siglongjmp(sigjmp_buf env, int val);

機能説明

sigsetjmp() によって、以前に env に保管されたスタック環境の 場合、siglongjmp() 関数は、すべてのスタック環境 、および sigsetjmp() によって保管されたかどうかにより、シグナル・マスクをオプションで復元します。sigsetjmp() および siglongjmp() 関数は、非ローカル goto を実行する方法を提供します。

env は、sigjmp_buf 構造体のアドレスです。

val は、siglongjmp() からの戻り値です。

シグナル・マスク復元のオプション機能を除けば、siglongjmp() は longjmp() に似ています。sigsetjmp() と siglongjmp() の対、setjmp() と longjmp() の対、_setjmp() と _longjmp() の対、および getcontext() と setcontext() の対を 混用することはできません。sigsetjmp() によって保管されたスタック環境およびシグナル・マスクは、siglongjmp() でのみ復元できます。

オプションでのシグナル・マスクを含む現行のスタック環境が、sigsetjmp() への呼び出しによって、env に保管されます。siglongjmp() への以降の呼び出しにより、保管済み環境および シグナル・マスク (sigsetjmp() で保管された場合) が復元され、制御が sigsetjmp() 呼び出しに対応するプログラムのポイントへ戻されます。sigsetjmp() 呼び出しによって、指定 value が 戻された時点から実行が再開されます。制御を受信する関数にアクセス可能な (レジスター変数を除いた) すべての変数に、siglongjmp() の呼び出し時に保持していた値が 含まれています。レジスター変数の値は、予測不可能です。sigsetjmp() と siglongjmp() の間の呼び出しで変更される、非揮発性の auto 変数も予測不可能です。
注 :
  1. siglongjmp() を呼び出した場合には、sigsetjmp() への対応する 呼び出しが行われた関数を、最初に戻す必要はありません。sigsetjmp() を呼び出す関数が戻った後に siglongjmp() を呼び出すと、予測不可能なプログラムの動作が発生します。
  2. XPLINK ルーチンにジャンプして戻るために siglongjmp() を使用すると、それより前の sigsetjmp() (または getcontext()、その他) が呼び出された後、および siglongjmp() が呼び出される前に、XPLINK ルーチンによって発行されたすべての alloca() 要求はバックアウトされます。これらの alloca() 要求によって取得されたすべてのストレージは、XPLINK ルーチンが再開される前に解放されます。
  3. XPLINK 以外のルーチンにジャンプして戻るために siglongjmp() を使用すると、sigsetjmp() の後および siglongjmp() の前に発行された alloca() 要求はバックアウトされません。

siglongjmp() に渡す value 引数は、ゼロ以外でなければなりません。ゼロ引数を value に指定すると、siglongjmp() でその位置 の値 1 が置換されます。

siglongjmp() 関数は、通常の関数呼び出しや戻りメカニズムを使用しません。siglongjmp() によって保管シグナル・マスクが復元されるのは、ゼロ以外の savemask 引数を使用した sigsetjmp() への呼び出し によって、env パラメーターが初期設定された場合だけです。

C++ の特殊な動作: sigsetjmp() と siglongjmp() を使用して z/OS® XL C++ プログラム内の制御権を移動する場合、自動オブジェクトの破壊に関する動作は未定義です。 さらに、プログラム内の別の (宛先) ポイントに制御権を移動する例外がスローされたことによって、自動オブジェクトが破壊される場合、その同じ (宛先) ポイントに制御権を移動するスロー・ポイントで siglongjmp() を呼び出したときの動作は、未定義です。 これは z/OS XL C++z/OS XL C/C++ の ILC の両方のモジュールに当てはまります。 sigsetjmp() と siglongjmp() の、try()、catch()、および throw() との併用も未定義です。

XPLINK コンパイル C++ の特殊な動作: setjmp.h および ucontext.h に関連する制約事項は、以下のとおりです。
  1. Language Environment® V2R10 以降のライブラリーと共に実行され、jmp_bufsigjmp_buf、または ucontext_t の型を使用する、V2R10 以降の C コンパイラーでコンパイルされたすべての XPLINK プログラムは、Language Environment V2R9 以前からの C ヘッダーを付けてコンパイルすることはできません。
  2. いずれかのレベルの Language Environment ヘッダーを付けてコンパイルされた XPLINK 以外の関数は、jmp_bufsigjmp_buf、または ucontext_t のデータ項目を定義し、これらの渡されたデータ項目をもった getcontext()、longjmp()、 _longjmp()、setjmp()、_setjmp()、setcontext()、sigsetjmp()、または swapcontext() を 呼び出す XPLINK 関数に、それらのデータ項目を渡すことはできません。
  3. __XPLINK__ が定義されると、Language Environment V2R10 およびそれ以降のヘッダーは、setjmp()、getcontext()、および関連した関数が XPLINK ルーチンから呼び出される際に、これらの関数によって必要とされるより大きな jmp_bufsigjmp_buf、または ucontext_t の領域を定義します。__XPLINK__ が定義されないと、Language Environment V2R10 およびそれ以降のヘッダーは、より小さい jmp_bufsigjmp_buf、または ucontext_t の領域を定義します。V2R10 より前の Language Environment ヘッダーも、これらのデータ域がより小さいバージョンを定義します。XPLINK 関数が、小さい jmp_bufsigjmp_buf、または ucontext_t の領域を 持った setjmp()、getcontext()、または類似の関数を呼び出す場合、渡された (小さすぎる) データ域の終端を超えて C ライブラリーを保管しようとすると、ストレージ・オーバーレイまたはプログラム・チェックが発生する場合があります。

戻り値

siglongjmp() は、値を戻しません。

文書化される errno 値はありません。

この例では、スタック環境およびシグナル・マスクが、ステートメント if(sigsetjmp(mark,1) != 0) ...

で保管されます。

システムで最初に if ステートメントが実行 される際、環境の保管時に sigsetjmp() は 0 を戻すので、mark に環境およびシグナル・マスク が保管され、条件が偽に設定されます。 sigsetjmp() has been called

というメッセージが出力されます。
関数 p() への以降の呼び出しで、ローカル・エラー条件についてテストされます。これにより siglongjmp() が実行されることがあります。その場合、制御は mark で保管された環境 を使用するオリジナルの sigsetjmp() 関数に戻され、シグナル・マスクを復元します。-1 が siglongjmp() 関数からの戻り値であるため、このときは、条件は真です。この場合、例ではブロック中のステートメントが実行され、siglongjmp() has been called というメッセージが出力されます。そのあと、recover() 関数が実行され、プログラムが終了します。
#define _POSIX_SOURCE
#include <stdio.h>
#include <setjmp.h>

sigjmp_buf mark;

void p(void);
void recover(void);

int main(void)
{
   if (sigsetjmp(mark) != 0) {
      printf("siglongjmp() has been called¥n");
      recover();
      exit(1);
      }
   printf("sigsetjmp() has been called¥n");
⋮
   p();
⋮
}

void p(void) {
   int error = 0;
⋮
   error = 9;
⋮
   if (error != 0)
      siglongjmp(mark, -1);
⋮
}

void recover(void) {
⋮
}

関連情報