ゼロ除算でシステムを止めないために―PL/IにおけるONユニットの「正しい」作法
現場の若い衆から、「バッチがU0000(システムアベンド)で落ちて、夜中の障害対応呼び出しが辛い」という泣き言をよく聞く。特に多いのが、メンテナンスされてきた古いプログラムにおける、予期せぬゼロ除算(ZERODIVIDE)だ。
メインフレームの世界では、一度の演算エラーが数百万件のトランザクションを止めるトリガーになる。今日は、PL/Iにおける`ON ZERODIVIDE`を使った、泥臭くも堅牢なエラーハンドリングについて、我々ベテランが現場でどうやってこの「爆弾」を処理しているか、その知見を共有しよう。
なぜ「ONユニット」なのか
PL/Iの強力な特徴の一つが、この例外処理機構だ。他言語のようにいちいち`IF divisor = 0 THEN…`と書くのも大切だが、計算ロジックが複雑化すると、どうしても抜け漏れが出る。
`ON ZERODIVIDE`を適切に定義しておけば、プログラム内のどこでゼロ除算が発生しようとも、制御をエラーハンドリングルーチンへ強制的に飛ばすことができる。システムアベンドを回避し、ログを残して「エラーレコードとして別ファイルへ退避させ、処理を継続する」という、基幹システムに求められる「止まらない処理」が可能になるわけだ。
実践的なエラーハンドリング構造
まずは、現場でそのまま使えるテンプレートを見てほしい。ポイントは、エラー発生時に「どこで」「どの値で」落ちたかを特定するための情報を確実に残すことだ。
/i
MAIN_PROC: PROCEDURE OPTIONS(MAIN);
/ — 宣言部 — /
DCL DIVIDEND FIXED DEC(15,2);
DCL DIVISOR FIXED DEC(15,2);
DCL RESULT FIXED DEC(15,2);
DCL ERR_MSG CHAR(80) VAR;
/ — ゼロ除算発生時のハンドラ設定 — /
ON ZERODIVIDE BEGIN;
/ エラーログを出力し、異常フラグを立てて処理を続行させる /
PUT SKIP LIST(‘ ゼロ除算エラー発生 ‘);
PUT SKIP LIST(‘被除数:’, DIVIDEND, ‘ 除数:’, DIVISOR);
/ ゼロ除算の結果を0として扱うか、またはエラー用フラグを立てる等の処理 /
RESULT = 0;
/ 必要に応じてシステムログやVSAMエラーログへ書き出す /
/ CALL WRITE_ERROR_LOG(DIVIDEND, DIVISOR); /
GOTO NEXT_RECORD; / 処理を中断せず、次のレコードへスキップする /
END;
/ — メイン処理ループ — /
DO WHILE (READ_SUCCESS);
GET FILE(IN_FILE) INTO(REC_DATA);
DIVIDEND = REC_DATA.VAL_A;
DIVISOR = REC_DATA.VAL_B;
/ ここでゼロ除算が発生すると、自動的に上のONユニットへ飛ぶ /
RESULT = DIVIDEND / DIVISOR;
WRITE FILE(OUT_FILE) FROM(RESULT);
NEXT_RECORD:; / GOTOの飛び先 /
END;
END MAIN_PROC;
現場で役立つデバッグのコツと注意点
1. GOTOによる制御フローの理解
上記の例では`GOTO`を使っているが、これはONユニット特有のテクニックだ。ONユニット内で`GOTO`を使い、プログラム内のラベルへジャンプすることで、例外が発生した行の直後をスキップし、処理を安全な地点まで復帰させることができる。これを「異常回復処理」と呼ぶ。
2. コンパイルオプションとエスカレーション
PL/Iのコンパイラオプションで`CHECK`や`SIZE`を有効にしている場合、例外処理が重なりすぎるとスタックを圧迫することがある。大規模なバッチでは、ONユニット内での処理は「最小限のログ出力と状態フラグの更新」に留めるのが鉄則だ。
3. VSAMアクセスとの併用
もしあなたがVSAMを読み込んでいる最中にこのエラーが発生した場合、単に`GOTO`で飛ばすだけでなく、必ず`UNLOCK`や`ENDFILE`の整合性を確認すること。エラーが起きた瞬間にファイルがオープン状態のままだと、後続のリカバリでJCLの再実行が困難になるからだ。
最後に:なぜ私たちが「堅牢さ」にこだわるのか
「エラーハンドリングを完璧に書く」というのは、単なるプログラミングのテクニックではない。これは、運用担当者への敬意であり、夜中に呼び出されるエンジニア(自分たちを含む)への自己防衛だ。
`ON ZERODIVIDE`を使いこなし、何が起きてもシステムが「優雅に」エラーを報告し、自律的に回復できる設計を目指してほしい。これが、我々メインフレーマーが守り続けてきた「信頼性」という名の言語化できない技術だ。
何か詰まったら、いつでも聞け。仕様書には載っていない「現場の泥臭い知恵」なら、いくらでも授けよう。
