IBM i oci8.so でセグメンテーション障害(core dumped)

IBMiとOracleで嵌り事象に遭遇したので、備忘録として。

## 突然のセグメンテーション障害(core dumped)
IBMi 環境下のPHP`oci8.so`を使用して、ユーザーのPHPアプリケーションテストをしたところ、ある日突然なんのエラーメッセージも出力されず「セグメンテーション障害(core dumped)」となり、PHPアプリケーションが落ちてしまう様になった。エラー時に出力された、スプールは以下の通り。

```txt
 MCH6801    エスケープ            40   20/09/07  20:04:46.275123  QP2USER2     QSYS        *STMT    QP2USER2    QSYS        *STMT
                                      送信元モジュール. . . . . :   QP2API
                                      送信元プロシージャー. . . :   runpase_common__FiPvT2
                                      ステートメント. . . . . . :   5
                                      送信先モジュール. . . . . :   QP2API
                                      送信先プロシージャー. . . :   runpase_common__FiPvT2
                                      ステートメント. . . . . . :   5
                                      メッセージ. . :   オブジェクトQPADEV0001USHIDAY   505789のオフセット
                                        X'0000000000000018'のオブジェクト・ドメインまたは記憶域保護エラー。
                                      原因－－プログラムは，ブロック化された命令を使用しようとしたか，システム・ド
                                        メイン・オブジェクトをアクセスしようとしたか，あるいは保護されたページを間
                                        違って使用しようとしました。違反タイプは4です。違反タイプは以下のタイプ
                                        のエラーを示します。1-オブジェクト・ドメイン違反。2-テスト・ポインター
                                        ・ターゲット・アドレス可能度(TESTPTA)違反。3-読み取り保護エラー。
                                        4-書き込み保護エラー。5-実行保護エラー。空間クラスはX'08'です。空間
                                        クラスは，記憶域保護エラーまたは空間ポインターのTESTPTA違反の空間のタイ
                                        プを示します。00- 1次関連空間（空間オブジェクトを含む）。01- 2次関連空
                                        間。02-自動記憶域用の暗黙の処理空間。03-静的記憶域用の暗黙的処理空間。
                                        04-活動化グループに基づくヒープ記憶域の暗黙の処理空間。05-定数空間。
                                        06-ハンドルに基づくヒープ記憶域用の空間。07-テラスペース・オフセット
                                        X'0000000000000018'。08- I5/OS PASEメモリー・アドレス
                                        X'0000000000000018'のテラスペース。X'80000000000000000000040050000018'は
                                        ，保護エラーまたは空間ポインターのTESTPTA違反の記憶域へのポインターです
                                        。一部の違反は，低システム機密保護レベルで抑制されている場合があります。
 CPFB9C6    エスケープ            40   20/09/07  20:04:46.438840  QP2FORK      QSYS        *STMT    QP0ZPCPN    QSYS        *STMT
                                      送信元モジュール. . . . . :   QP2FORK
                                      送信元プロシージャー. . . :   send_escape__FPcPvUi
                                      ステートメント. . . . . . :   11
                                      送信先モジュール. . . . . :   QP0ZPCPN
                                      送信先プロシージャー. . . :   Qp0zNewProcess
                                      ステートメント. . . . . . :   278
                                      メッセージ. . :   PASE FOR Iが終了しました。シグナル11,エラー・コード
  5770SS1 V7R2M0 140418                           ジョブ・ログ                     CSC2015   20/09/07  20:04:46 JST ページ    2
   ジョブ名 . . . . . . . . . :   QPADEV0001      ユーザー. . . . :   USHIDAY      番号 . . . . . . . . . . . :   505789
   ジョブ記述 . . . . . . . . :   USHIDAYJD       ライブラリー. . :   USHIDA
 MSGID     タイプ                 SEV 日付    時刻            FROM PGM     ﾗｲﾌﾞﾗﾘｰ     INST     TO PGM      LIBRARY     INST
                                        1。
                                      原因－－PASE FOR Iプログラムは，PASE FOR Iシグナル11のため終了しました
                                        。エラー・コード1は，現行ディレクトリーにコア・ファイルが書き込まれたこ
                                        とを示しています。このシグナルは，ジョブ・ログに表示される例外メッセージに
                                        対して作成されている可能性があります。回復手順－－エラーを訂正して，要求
                                        を再試行してください。エラーの詳細説明－－コア・ファイルが書き込まれてい
                                        る場合には，PASE FOR I 'DBX'コマンドでそれを調べてください。PASE FOR
                                        Iコマンドは，対話式ジョブでプログラムQP2TERMを呼び出すことにより表示され
                                        るコマンド行で入力できます。
 CPF24A3    エスケープ            40   20/09/07  20:04:46.439263  QMHSNDPM     QSYS        0C79     QLEAWI      QSYS        *STMT
                                      送信先モジュール. . . . . :   QLEDEH
                                      送信先プロシージャー. . . :   Q LE leDefaultEh2
                                      ステートメント. . . . . . :   175
                                      メッセージ. . :   呼び出しスタックのカウンター・パラメーターの値が正しくな
                                        い。
                                      原因－－呼び出しスタックのカウンター・パラメーターに指定した値3が正しくあ
                                        りません。この値はAPIのパラメーター番号7に指定されました。回復手順－
                                        －呼び出しスタックのカウンター・パラメーターの値を訂正して要求を再試行して
                                        ください。この値は0以上でなければなりませんが，呼び出しスタックの項目数
                                        より大きくすることはできません。
 CEE9901    診断                  30   20/09/07  20:04:46.439299  QLEAWI       QSYS        *STMT    QP0ZPCP2    QSYS        *STMT
                                      送信元モジュール. . . . . :   QLETOOL
                                      送信元プロシージャー. . . :   Q LE CPF24A3_handler
                                      ステートメント. . . . . . :   9
                                      送信先モジュール. . . . . :   QP0ZPCP2
                                      送信先プロシージャー. . . :   _CXX_PEP__Fv
                                      ステートメント. . . . . . :   *N
                                      メッセージ. . :   アプリケーション・エラー。CPFB9C6は，QP0ZPCPNによっ
                                        てステートメント0000000278命令X'0000'で監視されていません。
                                      原因－－例外が発生して処理されなかったので，アプリケーションは異常終了しまし
                                        た。未処理例外が送られるプログラムの名前はQP0ZPCPN QP0ZPCPN
                                        Qp0zNewProcessです。プログラムは，このメッセージが送られた時に高水準言語ス
                                        テートメント番号0000000278で停止されました。複数のステートメント番号が表
                                        示された場合には，プログラムは最適化されたILEプログラムです。最適化によ
                                        って単一ステートメント番号を判別することはできません。*Nが値として表示さ
                                        れた場合には，実際の値が使用できなかったことを意味します。回復手順－－前
                                        にリストされた低レベル・メッセージを参照して，例外の原因を突き止めてくださ
                                        い。エラーを訂正してから，要求を再試行してください。
 CPC1219    完了                  50   20/09/07  20:04:46.439427  QWTPITP2     QSYS        0645     *EXT                    *N
                                      メッセージ. . :   このジョブは異常終了した。
                                      原因－－このジョブが異常終了する原因となるエラーが起こりました。回復手順－
                                        －このジョブのジョブ・ログで，以前にリストされているメッセージを参照してく
                                        ださい。エラーを訂正して，要求を再試行してください。

```

結果的には、以前ユーザーは、`Oracle 11g`を使用していたのだが、今回から`12c`に変更されており、`12c`はユーザーに紐付く省略の`Defaultプロファイル`のパスワード期限が、180日だった事が原因でした。

## 事象のまとめ

今回の事象をまとめると以下の通り。

- PHP on IBMi アプリケーションで、Oracle DBに接続。
- 接続時には、`セグメンテーション障害(core dumped)`となり、実行カレントディレクトリに`core`のメモリダンプが吐き出されて異常終了となる。
- Zend Server,コミュニティ版PHPどちらでも同様の現象となる。
- 開発用Windowsで同様の処理をしても、正常に処理される。
- IBMiからJava(JDBC)経由のアプリケーションでは、正常に処理される。
- 旧Oracle 11gに接続先を向けると、正常に処理される。（この辺りで、ようやく12c固有の問題と判断が付きました）
- IBMi上のSQLPlusでは、正常にログイン出来る。（ムムッ、なにやら不穏なワーニング`ORA-28002: the password will expire within 7 days`が...）

```sh
./sqlplus user/pwd@hostname:1521/database

SQL*Plus: Release 10.2.0.5.0 - Production on Mon Sep 7 21:49:09 2020
Copyright (c) 1982, 2010, Oracle.  All Rights Reserved.
ERROR:
ORA-28002: the password will expire within 7 days
```

どうも原因は、これのようで、IBMiの`oci8.so`または`Oracle Instant Client`の何れかが、このワーニングをハンドリング出来ていないのかな？通常なら、7日間の猶予があるようで、それでlocalやJavaは問題が表面化せず動作しているのかもしれません。

## 解決方法
デフォルトプロファイルのパスワード期限を無期限にするか、対象のプロファイルのパスワードを無期限にします。本来は、デフォルト変えてまうより、アプリケーション接続ユーザー様のプロファイルにするべきでしょうね。

1. プロファイルの期限を設定
2. アカウントロックを解除／パスワード再設定

```sql
# SQLplusで接続する
./sqlplus user/pwd@hostname:1521/database

# 無期限設定
alter profile DEFAULT limit PASSWORD_LIFE_TIME unlimited;
alter profile プロファイル名 limit PASSWORD_LIFE_TIME unlimited;

# 設定確認
SELECT * FROM dba_profiles WHERE PROFILE='DEFAULT' AND RESOURCE_NAME='PASSWORD_LIFE_TIME';

ROFILE
--------------------------------------------------------------------------------
RESOURCE_NAME                    RESOURCE
-------------------------------- --------
LIMIT
--------------------------------------------------------------------------------
COM INH IMP
--- --- ---
DEFAULT
PASSWORD_LIFE_TIME               PASSWORD
UNLIMITED
NO  NO  NO
```

Oracleのプロではないので、バージョン変わる時に流儀が変わっていると、嵌ることがよくあります。
因みに、明示的にユーザーをロックしたり、パスワードをExpireさせた時は、oci8.soから「～Loked～」など、メッセージが返され、**Coredumped** で落ちる事はないので、自然と180日で切れて、猶予期間が存在する時だけ起こる事象かもしれません。