bea ホーム | 製品 | dev2dev | support | askBEA
BEA Logo Tuxedo
 ドキュメントのダウンロード   サイトマップ   用語集 
検索
0

Tuxedo C リファレンス

 Previous Next Contents View as PDF  

TRY(3c)

名前

TRY()−例外復帰インターフェイス

形式

#include <texc.h>

TRY
try_block
[ CATCH(
exception_name) handler_block] ...
[CATCH_ALL
handler_block]
ENDTRY

TRY
try_block
FINALLY
finally_block
ENDTRY

RAISE(
exception_name)
RERAISE

/* 例外の宣言 */
EXCEPTION
exception_name;

/* アドレス (アプリケーション) 例外の初期化 */
EXCEPTION_INIT(EXCEPTION
exception_name)

/* ステータス例外の初期化 (ステータスを例外にマップ) */
exc_set_status(EXCEPTION *
exception_name, long status)

/* ステータス例外をステータスにマップ */
exc_get_status(EXCEPTION *
exception_name, long *status)

/* 例外の比較 */
exc_matches(EXCEPTION *
e1, EXCEPTION *e2)

/* stderr にエラーを出力 */
void exc_report(EXCEPTION *
exception)

機能説明

TRY/CATCH インターフェイスは、ステータス変数 (たとえば、errno や RPC オペレーションで返されるステータス変数) を使用せずに例外を処理する機能を提供します。これらのマクロは texc.h ヘッダ・ファイルに定義され、このヘッダ・ファイルは tidl(1) で作成されるすべてのヘッダ・ファイルに自動的にインクルードされます。

TRYtry_block は C または C++ の宣言文とステートメントのブロックであり、このブロック内で例外が発生します (例外の発生と関係のないコードは try_block の前、あるいは後に配置します)。TRY/ENDTRY の対により、例外のスコープ、つまり例外を検出するコード領域が構成されます (C 言語のスコーピングとは異なります)。これらのスコープはネストすることができます。例外が発生すると、例外を処理するためのアクション (CATCH または CATCH_ALL クローズ)、あるいはスコープを完結するためのアクション (FINALLY クローズ) に対応するアクティブなスコープを検索することにより、エラーがアプリケーションにレポートされます。スコープが例外処理を行えない場合には、そのスコープは終了し次の上位レベルで例外が生成されます (例外スコープのスタックをアンワインドします)。実行は、処理が行われた箇所の後から再開します。エラーが発生した箇所から実行を再開することはありません。いずれのスコープでも例外が処理されない場合には、プログラムは終了します (userlog(3c)abort(3) を呼び出すことにより、メッセージがログに書き込まれます)。

CATCH (exception_name) handler_block は、存在しなくても複数回記述してもかまいません。各 handler_block は C または C++ の宣言文またはステートメントであり、対応する例外 (exception_name) の処理を行います (通常、障害からリカバリするためのアクションが指定されます)。例外が try_block 内のステートメントで発生した場合には、その例外に対応する最初の CATCH クローズが実行されます。

CATCH または CATCH_ALL handler_block 内では、現レベルの例外は EXCEPTION ポインタ THIS_CATCH により参照できます (たとえば、例外値に基づくロジックや、例外値の出力など)。

例外がいずれの CATCH クローズでも処理できない場合には、CATCH_ALL クローズが実行されます。デフォルトでは CATCH または CATCH_ALL クローズで処理される例外に対しては、それ以上のアクションは取られません。CATCH_ALL クローズが存在しない場合には、try_block が他の try_block にネストされているものと想定し、次の上位の try_block で例外が発生します。ANSI C コンパイラを使用した場合には、ハンドラ・ブロック内で使用されるレジスタと自動変数に volatile 属性を付加して宣言しなければなりません (setjmp/longjmp を使用するブロックの場合も同様です)。また、例外を発生する関数からの出力パラメータと戻り値は、不明であることに注意してください。

CATCH または CATCH_ALL handler_block 内では、現レベルの例外は RERAISE ステートメントにより、次の上位のレベルに伝播されます (例外が再度発生します)。RERAISE ステートメントは、handler_block のスコープ内 (つまり handler_block により呼び出された関数内ではありません) になければなりません。検出はできますが、完全には処理できない例外はすべて出し直さなければなりません。ほとんどの場合、ハンドラはすべての例外を処理するようには書かれていないので、CATCH_ALL ハンドラは例外を再度発生させる必要があります。アプリケーションは、例外が該当するスコープで発生し、ハンドラ・ブロックが適切な処理を行って該当するステータスを変更するように書かれなければなりません (たとえば、ファイルのオープン中に例外が発生した場合には、そのレベルの例外関数は、オープンされていないファイルをクローズしてはいけません)。

例外は、RAISE (exception_name) ステートメントを使用してどこででも発生させることができます。このステートメントにより、例外は現在の try_block から伝播を開始して、処理が行われる上位レベルに到達するまで出し直されます。

FINALLY クローズは、例外の発生に関係なく、try_block の後で実行されるコードの終局ブロックを指定するのに使用します。例外は try_block 内で発生した場合には、finally_block が実行された後で出し直されます。このクローズは、終局コードを重複して使用しないように、つまり CATCH_ALL クローズ内と ENDTRY の後で二度繰り返して使用しないようにするためのものです。このクローズは通常、クリーンアップ作業を行い、例外の発生に関係なく (つまりブロックでの正常終了と異常終了の両方で) スコープがアンワインドする際にインバリアント (たとえば、共有データ、ロック) をリストアするのに使用します。FINALLY クローズは、同じ try_block に対しては CATCHCATCH_ALL クローズと一緒に使用することはできません。try_block をネストして使用します。

TRY ブロックを終了するには、ENDTRY ステートメントを使用しなければなりません。このステートメントは、例外が処理されコンテキストがクリーンアップされたことを確かめるために実行するコードを含んでいます。try_blockhandler_blockfinally_block には、return、ローカルではない jump、あるいは ENDTRY に到達せずにブロックを出る手法 (goto()break()continue()longjmp() など) を含めてはいけません。

このインターフェイスは、RPC オペレーションからの例外を処理するために提供されています。ただしこのインターフェイスは、すべてのアプリケーションで使用することのできる汎用のインターフェイスです。例外は、EXCEPTION の形式で宣言されます(これは複雑なデータ・タイプで、long integer のようには使用できません)。2 種類の例外があります。どちらも同じ方法で宣言されますが、初期化の方法は異なります。

1 番目の例外は、RPC 実行時プリミティブが出すオペレーティング・システムのシグナルと、例外に関連するステータス値を伝播するのに使用されます。ステータス値ごとに例外があらかじめ定義されています (たとえば、例外 rpc_x_no_memory が、ステータス rpc_s_no_memory に対して定義されています)。これらの例外は trpcsts.h ヘッダ・ファイルに宣言されています。必要必須ではありませんが (ステータス例外はあらかじめ定義されています)、ステータス例外はアプリケーションで宣言し、exc_set_status() マクロで初期化できます。このマクロには、初期化する EXCEPTION へのポインタとステータス値が必要です。status 例外に関連するステータス値は、exc_get_status() マクロを使用して取得できます。EXCEPTION へのポインタとステータス値が返される変数へのポインタが必要です。status 例外であれば、マクロの値は 0 であり、そうでなければ -1 です。

2 番目の例外はアプリケーション例外を定義するのに使用されます。EXCEPTION_INIT() マクロを呼び出して初期化されます。例外のアドレスは address 例外内の値として格納されます。この値は単一のアドレス空間内でのみ有効であり、例外が自動変数の場合には変更されることに注意してください。このため address 例外は静的変数あるいは外部変数として宣言し、自動変数あるいはレジスタ変数として宣言すべきではありません。exc_get_status() マクロは、address 例外では -1 となります。この例外で exc_set_status() マクロを使用すると status 例外となります。

exc_matches マクロは、2 つの例外を比較するのに使用します。同一であるためには、どちらの例外も同じタイプであり、同じ値を持たなければなりません (つまり、status 例外に対しては同じステータス値を持つか、address 例外に対しては同じアドレスを持ちます)。この比較は、上記の CATCH クローズで使用されます。

ステータス例外が発生した場合の通常の処理は、ステータス値を表示するか、より好ましい方法としてはステータス値が何であるかを示す文字列を表示することです。文字列を標準エラー出力に表示するのであれば、文字列を 1 回の操作で表示できるように status 例外へのポインタを付加して関数 exc_report() を呼び出します。

CATCH_ALL 
{
exc_report(THIS_CATCH);
}
ENDTRY

文字列に対して他の処理を行う場合には (たとえば、エラーをユーザ・ログに出力する)、exc_get_status()THIS_CATCH で使用し、ステータス値を取得できます (THIS_CATCHEXCEPTION に対するポインタであり、EXCEPTION 自体ではありません)。dce_error_inq_text() を使用して、ステータス値の文字列を取得することができます。

CATCH_ALL 
{
unsigned long status_to_convert;
unsigned char error_text[200];
int status;

exc_get_status(THIS_CATCH,status_to_convert);
dce_error_inq_text(status_to_convert, error_text, status);
userlog(“%s”, (char *)error_text);
}
ENDTRY

注記 マルチスレッドのアプリケーション中のスレッドは、TPINVALIDCONTEXT を含め、どのコンテキスト状態で実行していても、TRY/CATCH インターフェイスを呼び出すことができます。

例外とステータス復帰をいつ使用するか

RPC オペレーションのステータスは、各オペレーションごとにステータス変数を定義することにより決定できます ([comm_status} と [fault_status] パラメータは、ACF (Attribute Configuration File) で定義されます)。ステータス復帰インターフェイスは、X/Open RPC 仕様で提供される唯一のインターフェイスです。fault_status 属性は、不適切なパラメータ、リソース不足、コーディング・エラー等によりサーバ上で発生したエラーが、補助的なステータス引数や戻り値でレポートされることを示しています。同様に comm_status 属性は、RPC コミュニケーション障害が補助的なステータス引数や戻り値でレポートされることを示します。ステータス値を利用する処理は、各コールごとに起こり得るエラーに対して指定されたリカバリを行う (コールごとの) きめ細かいエラー処理と、障害の時点での再試行が必要な場合にはうまく機能します。欠点としては、コールがローカルなものであってもリモートなものであっても、いずれの場合にも透過性がない点が挙げられます。リモート・コールには追加のステータス・パラメータ、あるいは void の代わりにステータスの戻り値が必要になります。従ってアプリケーションでは、ローカルと分散コード間で調整を行うプロシージャ宣言が必要です。

TRY/CATCH 例外復帰インターフェイスは、OSF/DCE 環境からのアプリケーション移植性のためにも提供されています。このインターフェイスは、すべての環境で利用できるものではありません。しかし、プロシージャ宣言をローカルと分散コード間で調整する必要がないという利点があり、既存のインターフェイスを保持できます。各プロシージャ・コールは固有の障害チェックやリカバリ・コードを持つ必要がなく、エラー・チェッキングを簡素化できます。あるレベルでエラー処理が行えない場合には、プログラムは、「エラーが検出されたが修正可能である」などのシステム・エラー・メッセージを出力して終了します (メッセージを省略すると、エラー・チェッキングはより簡単になります)。例外は、大まかな例外処理を行う場合には有用です。

組み込み例外

表 13 に示す例外は、この例外インターフェイスで使用するために組み込まれている例外です。最初の TRY クローズはシグナル・ハンドラを設定し、以下にリストされたシグナル (無視されることがなく、補足可能なもの) を補足します。その他の例外は DCE 対応のプログラムでの移植性のためにのみ定義されたものです。

表 13 組み込み例外

例外

機能説明

exc_e_SIGBUS

処理できない SIGBUS シグナルが発生しました。

exc_e_SIGEMT

処理できない SIGEMT シグナルが発生しました。

exc_e_SIGFPE

処理できない SIGFPE シグナルが発生しました。

exc_e_SIGILL

処理できない SIGILL シグナルが発生しました。

exc_e_SIGIOT

処理できない SIGIOT シグナルが発生しました。

exc_e_SIGPIPE

処理できない SIGPIPE シグナルが発生しました。

exc_e_SIGSEGV

処理できない SIGSEGV シグナルが発生しました。

exc_e_SIGSYS

処理できない SIGSYS シグナルが発生しました。

exc_e_SIGTRAP

処理できない SIGTRAP シグナルが発生しました。

exc_e_SIGXCPU

処理できない SIGXCPU シグナルが発生しました。

exc_e_SIGXFSZ

処理できない SIGXFSZ シグナルが発生しました。

pthread_e_badparam


pthread_e_defer_q_full


pthread_e_existence


pthread_e_in_use


pthread_e_nostackmem


pthread_e_nostack


pthread_e_signal_q_full


pthread_e_stackovf


pthread_e_unimp


pthread_e_use_error


exc_e_decovf


exc_e_exquota


exc_e_fltdiv


exc_e_fltovf


exc_e_fltund


exc_e_illaddr


exc_e_insfmem


exc_e_intdiv


exc_e_intovf


exc_e_nopriv


exc_e_privinst


exc_e_resaddr


exc_e_resoper


exc_e_subrng


exc_e_uninitexc



 

名前の後に &dlq;q; が付加された同じ例外コードが定義されています (exc_e_SIGBUS は、exc_SIGBUS_e とも定義されています)。同等のステータス・コードが同様な名前で定義されていますが、&dlq;_e_” は “_s_&d“変更されています (exc_e_SIGBUS は、exc_s_SIGBUS ステータス・コードと同等です)。

警告

OSF/DCE では、ヘッダ・ファイルは exc_handling.h と命名されますが、BEA Tuxedo ATMI システムのヘッダ・ファイルは texc.h です。同じソース・ファイルで DCE と BEA Tuxedo ATMI システムの例外処理を両方使用することはできません。また 1 つのプログラム内では、シグナル例外の処理は DCE か BEA Tuxedo ATMI システムのいずれか一方でしか行えません。1 つのプログラム内で BEA Tuxedo ATMI システム/TxRPC スタブと OSF/DCE スタブを統合する方法については、『TxRPC を使用した BEA Tuxedo アプリケーションのプログラミング』を参照してください。

このインターフェイスを用いてプログラムをリンクする場合には、$TUXDIR/lib/libtrpc.a をインクルードしなければなりません。

使用例

例外を使用する C 言語のソース・ファイルを以下に示します。

#include <texc.h>  

EXCEPTION badopen_e; /* 不正な open() に対する例外宣言 */

doit(char *filename)
{
EXCEPTION_INIT(badopen_e); /* 例外の初期化 */
TRY get_and_update_data(filename); /* 処理の実行 */
CATCH(badopen_e) /* 例外 - open() が異常終了しました */
fprintf(stderr, “Cannot open %s¥en”, filename);
CATCH_ALL /* 他のエラーの処理 */
/* 利用できない rpc サービスの処理 ...*/
exc_report(THIS_CATCH)
ENDTRY
}
/*
* 出力ファイルのオープン
* リモート・データ項目の取得
* ファイルへの書き込み
*/
get_and_update_data(char *filename)
{
FILE *fp;
if ((fp == fopen(filename)) == NULL) /* 出力ファイルのオープン */
RAISE(badopen_e); /* 例外の生成 */
TRY
/* このブロックでは、ファイルは正常にオープンされました -
* FINALLY を使用してファイルをクローズします
*/
long data;
/*
* RPC コールの実行 -
* 呼び出し側関数 doit() に対して例外を出します
*/
data = remote_get_data();
fprintf(fp, “%ld¥en”, data);
FINALLY
/* 例外が発生してもしなくても、ファイルをクローズします */
fclose(fp);
ENDTRY
}

関連項目

tidl(1)userlog(3c)

UNIX システムのリファレンス・マニュアルの abort(2)

TxRPC を使用した BEA Tuxedo アプリケーションのプログラミング

 

Back to Top Previous Next
Contact e-docsContact BEAwebmasterprivacy