以下、図面を用いて各実施形態を説明する。まず第一の実施形態では、あるプロセスを強制終了する際に、OSが、そのプロセスで実行されるプログラムが構造化例外処理に対応した実行時ライブラリで実行されているかを判定する。そして、実行されるプログラムが構造化例外処理に対応する場合、OSはそのプロセスの終了時に実行時ライブラリに制御を移して例外処理等の特定の処理(以下「特定処理」)を実行させる。この場合、特定処理には上述したfinallyで定義される後処理も含まれ、例えば、特定処理として、プロセス終了に伴うシステムの回復処理が行われる。特定処理の終了後、OSはプロセスを終了させる。以下第一の実施形態での処理方法について説明する。
図2は、第一の実施形態である計算機の概要例を示す図である。計算機200は、CPU201、メモリ203、外部記憶装置204、入出力装置202を有する一般的な計算機である。外部記憶装置204には、計算機200のCPU201が実行するOSを構成するファイル210が格納されている。加えて、外部記憶装置204には、OSが実行するプロセスとして実行されるプログラムとして、実行時ライブラリ212、アプリケーションプログラムファイル213が格納されている。
実行時ライブラリ212は、構造化例外処理に対応したプログラミング言語によって作成されたプログラムを、プロセスで実行するための実行環境を提供する。具体的には、実行時ライブラリ212は、プログラム開始終了の処理、OSの呼び出し、メモリ管理等の、プログラム実行に必要な基本的な処理を、プログラムに提供する。
アプリケーションプログラムファイル213は、構造化例外処理に対応したプログラミング言語で作成されたプログラムファイル(プログラムのデータ)である。プログラミングファイル213はヘッダを有し、実行時に使用される(以下「リンクする」とも言う)実行時ライブラリ212の名前を、そのヘッダに含んでいる。
また、外部記憶装置204は、OS210の実行時にCPU201が参照するOS環境設定ファイル211も保持している。OS環境設定ファイル211は、計算機200にインストールされている、強制終了処理時に実行される実行時ライブラリ212の情報を保持する。尚、「強制終了処理」とは、以下で説明する、プロセスの強制終了時の実行時ライブラリやスレッドで行われる構造例外処理を指すものとする。
図2では、メモリ203にOS100がロードされて、いくつかのプロセスがCPU201によって実行されていることが示されている。このように、外部記憶装置204に格納されたプログラムは、メモリ203にロードされた後、CPU201で実行される。また本図では、1つのプロセス110が、実行時ライブラリ120上でアプリケーションプログラム130を実行していることを示している。ここで、メモリ203内に記載されている実行時ライブラリ120とアプリケーションプログラム130は、それぞれファイル212と213のメモリ203内のイメージを示す。
図1は、第一の実施形態におけるアプリケーションプログラムを実行するプロセス110とOS100の論理的な内部構造例を示す図である。以下、説明を簡単にするため、プログラムを主語として説明を行う。しかし、実際には、CPU201が説明される処理を実行することとなる。
OS100は、プロセス実行時の例外をプロセスに配信する例外通知モジュール101、及びOS100に登録されている実行時ライブラリ120を実行しているプロセスを強制終了する場合に、強制終了の対象となるプロセスに強制終了の旨を通知する強制終了通知モジュール102を有している。
また、OS100は、強制終了通知の配信対象となる実行時ライブラリ120を定義する実行時ライブラリテーブル103を保持している。実行時ライブラリテーブル103には、実行時ライブラリ212の名前と、その実行時ライブラリ212に含まれ、OS100からの強制終了通知を処理するモジュールのアドレスに関する情報を保持する。
図1に示した例では、実行時ライブラリテーブル103は、実行時ライブラリAの情報を格納しており、その強制終了通知を処理するモジュールは終了例外配信モジュール122である。
プロセス110では、構造化例外処理に対応した実行時ライブラリA120と、アプリケーションプログラム130が実行されている。プロセス110では、複数のスレッドがアプリケーションプログラム中のモジュールを実行している。
尚、簡単にプロセス、スレッド、モジュールを説明する。プログラムは、複数のモジュールから構成される。モジュールは、例えば、手続き型言語での関数や、オブジェクト指向言語でのメソッドに相当する。プロセスはプログラム実行のための資源管理の単位で、具体的には、プログラム実行に必要なアドレス空間の定義と対応付けられる。スレッドは、プロセスのアドレス空間にロードされたプログラム(モジュール等)内のコードを実行する単位となる。スレッドは、スレッドで現在実行されている命令のアドレスや、スレッドの実行状態を保存するスタック等を保持している。
実行時ライブラリA120は、例外配信モジュール121と終了通知配信モジュール122を含んでいる。例外配信モジュール121は、発生した例外を、その例外を発生したスレッドに配送する。終了通知配信モジュール122は、プロセス110が強制終了される場合に呼び出されて、プロセス110の終了処理を実施する。
まず、通常の構造化例外処理の流れを説明する。図3は、300に示したプログラムの実行中に例外が発生した場合の処理フロー例を示す図である。以下、図1のスレッド140が、図3の300のプログラムを実行しているとして説明する。又、「モジュールProcess」等の表現は、ある特定のモジュール(その特定のモジュールに「Process」というモジュール名が付与されている)を指すものとする。
モジュールProcessを実行するスレッド140は、構造化例外処理のtry文の実行中にモジュールSub1を呼び出し(ステップ301)、モジュールSub1を実行するスレッド140は、Sub2を呼び出す(ステップ302)。
尚、スレッド140は、1つのtry文を実行する前に、そのtry/catch/finally文の情報をスレッド140の例外処理リスト150に、一つのブロックとして記録する。この際、作成されたブロックは、例外処理リスト150の先頭に挿入される。ここで「例外処理リスト150」とは、スレッド140の実行の過程で出現し、まだ処理が完了していないtry/catch/finally文の情報を保持するリストである。例外処理リスト150は、1つのtry/catch/finally文を表現するブロックから構成され、メモリに格納される。
try文実行の前に格納された構造化例外処理に関するデータは、そのtry文に対応するFinally文の実行の前に例外処理リスト150から削除される。これらの処理を実施するために必要なプログラムコードは、モジュールのコンパイル時に生成される。
図4は、例外処理リスト150の構造例を示す図である。OS100は、スレッドの実行に必要なデータの1つとして、例外処理リスト150を保持している。例外処理リスト150は、1つのtry/catch/finally文に関する実行時の状態を保持する例外処理ブロック410を有する。そして、例外処理リスト150では、これらの例外処理ブロックがリスト構造となっている。
個々の例外処理ブロック410は、例外処理が定義されたときのスレッドのスタックポインタ、finally文がある場合はその開始アドレス、その時点で他に定義されている構造化例外処理に対応する例外処理ブロックへのリンクの情報を保持する。catch文が定義されている場合は、例外処理ブロック410は、catch文の情報を保持するcatchブロック430のリスト(catchブロックのリンク構造を有する構造体)への参照アドレスも保持する。
catchブロック420は、catch文毎に1つ作成される。個々のcatchブロック420は、ブロックに対応するcatch文が捕獲する例外の種類、対応するcatch文の開始アドレス、他のcatch文に対応するcatchブロック420への参照アドレスを示す情報を含む。
図4の例では、例外処理ブロック420とcatchブロック430がProcessモジュールの例外処理定義、例外処理ブロック410がSub1の例外処理定義に対応している。例外処理リスト150内の項目の順番は、最後に登録された構造化例外処理を記述する例外処理ブロック410がリストの先頭に登録されるようになっている。各例外処理ブロック410は、コンパイラが生成したコードによって、例外処理ブロック410に対応するFinally文が実行される直前に削除される。
図3に戻って処理手順の説明を続ける。ここで、モジュールSub2が、処理中にエラーを検出し、実行時ライブラリA120に例外生成を要求したとする(ステップ303)。実行時ライブラリA120は、要求を受けて、例外をスレッド140に配信する。
具体的には、要求を受けた実行時ライブラリA120は、スレッド140で例外配信モジュール121の実行を開始する。例外配信モジュール121は、スレッド140の例外処理リスト150を参照して、例外生成を要求したモジュールに対応する例外処理ブロック410を選択し、必要ならばそのブロック410に登録されている例外を捕獲するcatch文を含むcatchブロックを見つける。図4の例でいえば、catchブロック430が、Sub2の例外を捕獲するcatch文を含んでいる(ステップ304)。
次に例外配信モジュール121を実行するスレッド140は、例外処理リスト150に登録され、かつステップ304で見つけられたcatchブロック(ここではcatchブロック430)より前に例外処理リスト150に登録されている全ての例外処理ブロックに登録されたfinally文を実行する。図4の例でいえば、例外処理ブロック410が該当するので、スレッド140は、例外処理ブロック410に登録されているfinally処理を行う。その後、スレッド140は、先に選択されたcatchブロック430に登録されている、例外を捕獲するcatch文を実行し、それに付随するfinally文を実行する。
図3の例では、スレッド140は、モジュールsub2内のfinally文、モジュールsub1内のfinally文を実行する(ステップ305)。次にスレッド140は、モジュールProcess内のcatch文を実行し(ステップ306)、最後にモジュールProcess内のfinally文を実行する(ステップ307)。各々のfinally文実行の前に、各々のfinally文に対応する例外処理ブロック(ここでは例外処理ブロック410と420)は削除される。
図3の例では、プログラム自身がエラーを検出し例外を生成して通知する処理を説明したが、数値計算のオーバーフローやゼロ割り算のように、スレッド140を実行中のCPU201が例外を発生し、OS100が例外を検知する場合もある。この場合、OSの例外通知モジュール101が、プロセッサ例外の発生を実行時ライブラリA120の例外配信モジュール121に通知し、例外配信モジュール121が、例外を発生したスレッド140のコンテクストで例外処理リスト150に登録されている例外処理を実行する。
次に、本実施形態において、プロセス110が他のプロセスやOSから強制的に終了される場合の処理手順について説明する。図5と図6は、プロセスが強制終了される場合の処理の手順例を示す図である。図5は、OS100の強制終了通知モジュール102が行う手順例を示す図である。
強制終了の場合、プロセス110で実行されるスレッド自身が、例外処理の開始をプロセス110で実行される実行時ライブラリA120に要求することが出来ない。したがって、この場合OS100が、強制終了の対象となるプロセス110で実行される実行時ライブラリ120の特定のモジュール(ここでは、実行時ライブラリテーブル103に登録されたモジュール)を特定してそのモジュールに対して強制終了を通知する。
そして、特定されたモジュールは、プロセス110で実行されている全てのスレッドで特定処理、具体的には構成例外処理(finally処理のみ)を実行して全てのスレッドを終了させる。これにより、各スレッドの構成例外処理に定義されたfinally処理によって計算機システムの矛盾を解消してプロセスを終了することが出来る。以下、手順を説明する。
OS100は、プロセス110を強制終了するように要求されると、強制終了通知モジュール102を実行し、まず、強制終了対象のプロセス110(以下「対象プロセス110」)が、強制終了処理に対応する実行時ライブラリ212を実行しているか検査する(ステップ501)。具体的には、OS100は、プログラム130が実行時ライブラリテーブル103に登録されているライブラリとリンクしているか否かを確認することで、実行時ライブラリ212の実行の有無を判定する。尚、リンクの有無は、OS100が、プロセス110が実行しているアプリケーションプログラム130を構成するファイル213のヘッダに含まれる情報を参照して判定する。
対象プロセス110が実行時ライブラリテーブル103に登録されている実行時ライブラリ212とリンクしていないならば、通常のプロセス強制終了の処理として、OS100は、プロセス110に割り当てられたシステムリソースを解放し、プロセス110の実行を停止する(ステップ503)。
一方、対象プロセス110が実行時ライブラリテーブル103に登録されている実行時ライブラリ212とリンクしているならば、OS100は、強制終了通知モジュール102の実行に基づいて、対象プロセス110に割り込み可能なスレッドがあるか検査する(ステップ502)。
対象プロセス110に割り込み可能なスレッドが存在しないならば、OSは例外処理をあきらめて、通常の停止処理を実施する。これは、OS110から直接実行時ライブラリAの終了通知配信モジュール122の起動を指示できないため、プロセス110で実行されているスレッドに割り込むことで終了通知配信モジュール122の起動を指示する必要があるからである(ステップ503)。
一方、対象プロセス110に割り込み可能なスレッドがあるならば、OS100は、割り込み可能なスレッドを1つ選択する(ステップ504)。そしてOS100は、選択されたスレッドの実行に割り込んで、実行時ライブラリテーブル103に登録されている終了通知配信モジュール122に制御が移るようにスレッドのコンテクストを設定し、そのスレッドの実行を再開させる。この処理によって、割り込まれたスレッドは、OS100によって次回スケジュールされたときに、終了通知配信モジュール122を実行して、登録されている構造化例外処理を実行する(ステップ505)。
この後、OS100は、対象プロセス110内のすべてのスレッドの終了を待って(ステップ506)、プロセスの資源解放処理(ステップ503)を実施し、対象プロセス110の実行を終了させる。
尚、本実施形態では、対象プロセス110のすべてのスレッドの終了を待つとして説明したが、定められた所定の時間待って全てのスレッドが終了しなければ、OS100が全スレッドの終了を待たずにステップ503を実行して、対象プロセス110を終了しても良い。この待ち時間は、実行時ライブラリの設定値、プロセスの終了を指示するときに指定する、あるいは、プロセスの属性として設定する、といった方法で定めることが考えられる。
次に、対象プロセス110におけるスレッドの終了処理について説明する。図6は、実行時ライブラリA120の終了通知配信モジュール122の処理フロー例を示す図である。図5で選択されたスレッドは、図5に示すOS100の割り込み後、終了通知配信モジュール122の実行を行う。
この終了処理では、この処理を実行しているスレッド(図5で選択されたスレッド)以外の対象プロセス110内の全てのスレッドに対して、ステップ603〜ステップ605の処理が実行される。まず、終了通知配信モジュール122は、他の実行中のスレッドに登録されている例外処理があるか検査する。具体的には、終了通知配信モジュール122は、他の実行中のスレッドに例外処理リスト150が設定されているかを検査する(ステップ603)。
他の実行中のスレッドに例外処理リスト150が設定されていないならば、終了通知配信モジュール122は、何もしない。このスレッドは、プロセスの資源解放処理(ステップ503)により消去される。
他の実行中のスレッドに例外処理リスト150が設定されている場合、終了通知配信モジュール122は、そのスレッドに割り込み、そのスレッドでステップ606からの例外配送処理が実行されるようスレッドのコンテクストを設定し(ステップ604)、スレッドの実行を再開させる(ステップ605)。尚、スレッドが、この時点で割り込めない待機状態にある場合は、終了通知配信モジュール1122は、割り込みを割り込み対象のスレッドの管理する記憶領域に記録し、待機状態から復帰したときに、例外配送処理を実施するようにコンテクストを設定する。
割り込まれたスレッドは、処理が再開された後に、例外配送処理を実行する。具体的には、割り込まれたスレッドは、そのスレッドの例外処理リスト150に登録されているfinally文を実行する(ステップ606)。このとき、割り込まれたスレッドは、例外処理リスト150に登録されているcatch文は無視する。そして、スレッドの実行を終了する。この際、割り込まれたスレッドは、OS100に対して自身の終了を通知する(ステップ607)。
一方、ステップ504で選択されたスレッドは、終了通知配信モジュール122を実行して自分以外のスレッドへの通知を送信した後(ステップ602)、自分自身に登録されているfinally文を実行し(ステップ606)、処理を終了する(ステップ607)。
最後に、実行時ライブラリテーブル103への実行時ライブラリ120の登録について説明する。OS100は、実行時ライブラリテーブル103へ実行時ライブラリ212の情報を登録するためのアプリケーションインターフェース(以下「API」)を提供する。例えば、実行時ライブラリをOS100にインストールするときにOS環境設定ファイル211に実行時ライブラリ情報(モジュール等)を登録するAPIや、実行時ライブラリ120の初期化時に実行時ライブラリテーブル103にモジュール等の情報を登録するAPIをOS100が有するようにする。OS100は、起動時に、OS環境設定ファイル211よりインストールされている実行時ライブラリの情報を取り込み、実行時ライブラリテーブル103に登録する。
尚、OSが実行時ライブラリテーブル103を持つ代わりに、プロセス毎の管理データとして、強制終了時に呼び出す終了通知配信モジュール122のアドレスと、その終了通知配信モジュール122をプロセスの起動時にプロセス自身がOSに登録するためのインターフェイスをOS100が有し、実行時ライブラリ120の初期化時に、プロセスが終了通知配信モジュール122をOS100に登録してもよい。
また、本実施形態では、プロセス側の終了通知配信モジュール122を実行時ライブラリ120内に置いたが、この限りではない。例えば、ユーザが作成するプログラム内においても良い。
本実施形態により、プロセスが外部から強制的に終了される場合にも、その時点で登録されている特定処理(構造化例外処理)を実行できる。これにより、プロセスに、処理途中で中途半端になっている状態を回復する機会を与えることができる。
一般に、OS100に含まれないプログラムで回復処理を実現(例えばトランザクション処理)しようとすると、様々な異常の状態を想定した解析をしなければならないため、回復処理が複雑になり、長い時間がかかる。また、ログやジャーナルといった履歴の記録が必要であり、このための処理や記憶域が必要になる。
一方、構造化例外で回復処理を実装する場合、回復処理を簡単に記述でき、複雑な解析処理も低減されて回復処理も簡便になる。さらに、本実施形態を組み合わせれば、回復処理を記述した特定処理がプロセスを外部から終了させる場合にも実行されるため、短時間で必要な回復処理を実行できる。これにより、計算機システムを矛盾のない状態に素早く復旧させることが可能となり、計算機システム全体の可用性の向上が期待できる。また、短時間で回復処理が実施できることから、計算機システムの応答性能の向上にも繋がる。
次に、第2の実施形態について説明する。第1の実施形態では、プロセスを強制終了させる要求を受けたときに、OS100が対象プロセス110内の割り込み可能なスレッドに割り込んで、そのスレッドに終了通知配信モジュール122を実行させた。しかし、プロセスが異常な状態にある場合、対象プロセス110には、割り込み可能なスレッドがない場合も考えられる。本実施形態は、そのような場合に対応する方法を示す。
図7は、第2の実施形態における、OS100のプロセス起動処理の処理フロー例を示す図である。
OS100は、プログラムを実行するプロセス110を作成する時に、そのプロセス110用のアドレス空間を初期化し(ステップ701)、そのアドレス空間にプログラムや必要な実行時ライブラリをロードする(ステップ702)。
次にOS100は、プロセス110を強制終了させるときに割り込み可能なスレッドがない場合に備えて、終了配信処理モジュール122を実行するためのスレッド資源を割り当てておく。この割り当てでOS100のスケジューリング対象となるスレッドを生成する必要はなく、終了処理のときにここで割り当てた資源を使ってOS100がスレッドを起動し、そのスレッドが終了配信モジュール122を実行できるようにしておけばよい。又、OS100は、このスレッドを完全なスレッドとして生成して、必要なときまで待機させておいても良い(ステップ703)。
その後OS100は、プロセス110の初期スレッドを生成する(ステップ704)。これにより、プロセス110が実行可能な状態となる。
その後、OS100は、プロセス110の強制終了要求を受けると、ステップ703で用意したスレッドを実行可能な状態にして、終了通知配信モジュール122を実行させる。具体的には、図6で説明した通り、このスレッドは、モジュール122のステップ603ないし605で自身以外のスレッドに定義されたfinally文を実施させ、最後に自身の実行を終了する。
尚、本実施形態では、OS100が終了処理用のスレッドを新たに作成してプロセス110に割り当てるとしたが、実行時ライブラリ120が、プロセス110の開始時に終了処理用のスレッドを割り当てても良い。具体的には、実行時ライブラリ120があるプログラムの実行を開始する際に、実行時ライブラリ120自身が、終了処理用のスレッドを、そのプログラムを実行するプロセスに実行させるように設定する。
またOS100が、プロセス100の強制終了指示時に、終了通知配信モジュール122の実行を待機しているスレッドを実行可能状態とすることとしたが、このスレッドがプロセス間通信を使って他プロセスからの終了要求を待ち、プロセス間通信で要求を受信したときに、終了通知配信モジュール122の処理を実施するようにしても良い。
本実施形態により、プロセスの停止を要求した時点で割り込み可能なスレッドがない場合でも、実行時ライブラリに終了通知を配信できる。プロセス内のスレッドは、割り込みが可能になった時点で登録している例外処理のfinally文を実行して終了する。これにより、強制終了通知の配送をあきらめるよりも、登録されている構造化例外処理を実行できる可能性を高めることができ、プロセスが処理途中で中途半端になっている状態を回復する機会を増大できる。これは、システム全体の可用性の向上に繋がると期待できる。
次に、第三の実施形態として、プロセス強制終了時の構造化例外処理の実行を、選択的に定められるようにする方法を説明する。本実施形態では、プロセス強制終了時に、プログラムに記述されている構造化例外処理を実行するかどうかを、プログラムコードの属性として指定する方法を示す。
図8は、本実施形態でのプログラムのコードの例と、必要なデータ構造例を示した図である。図8の801で示されるコードでは、モジュールfunction1の記述の直前に、[doFinallyOnTerminate()]と記述している。これは、モジュールfunction1内の構造化例外処理について、プロセス110が強制終了された場合にfinallyを実行するように指定する記述である。また、図8の802で示されるコードでは、モジュールfunction1内のtryブロックの直前に、[doFinallyOnTerminate()]と記述している。これは、プロセス110が強制終了された場合に、このtryブロックのfinally処理を実行するよう指定する記述である。
これらの記述はプログラムをコンパイルするときにコンパイラによって認識され、コンパイラは、try文の実行の直前に、対応する例外処理ブロックを生成するコードを生成する。
図8では、本実施形態における例外処理ブロック810のデータ構造例をも示す。図4に示した例外処理ブロック410の内容に加えて、例外処理ブロック810は、プロセスの強制終了時にfinally文を実施するかどうかを示すフラグを格納する領域を持つ。コンパイラは、doFinallyOnTerminate属性が設定されているtry文を発見すると、その例外処理ブロック810のフラグをセットするコードを生成する。
第一の実施形態の終了通知配信モジュール122の処理では、ステップ603でスレッドに構造化例外処理が登録されているかどうかを判定していたが、本実施形態では、それに替えて、強制終了時のfinally処理実行が指定されている構造化例外処理が登録されているか判定して、指定されているスレッドでのみステップ606からの処理を実施させるようにする。さらに、ステップ606では、登録されている例外処理ブロック810を参照して、強制終了時にfinally処理実行するよう指定されているfinally文のみを実行する。
本実施形態により、登録されている構造化例外処理のうち、予め指定した処理だけを強制終了時に実行させるように指示できる。これにより、特定処理、具体的にはプロセス障害時の後処理を実施できる確率を高めることができ、システムの可用性の向上に繋がる。また、不要なfinally文を実行しないため、より素早くプロセスを停止でき、システムの復旧時間を短縮できる。
次に、上述した実施形態を他のシステム構成に応用する例について説明する。第4の実施形態は、クラスタ構成の計算機システムにおいて、プロセス障害時の系切り替え時間を短縮するために、上述した実施形態を適用する例である。
図9は、本実施形態のクラスタ構成例を示す図である。クラスタは、2台の計算機900と910、及び共有ディスク920を有する。計算機900と910は、ネットワークで相互に接続されている。それぞれの計算機で実行されるクラスタ制御部905と915が、ネットワークを介して互いの生死の状態を監視している(例えばハートビート信号等が用いられる)。
また、計算機900と910は、共有ディスク920とも接続している。また、図示していないが、計算機900と910には、クライアントとなる計算機がネットワーク経由で接続されている。
本実施形態では、計算機900が主系となっており、アプリケーション901を実行している。アプリケーション901は、強制終了処理を実装する実行時ライブラリ904の元で実行され、いくつかのスレッド902を実行している。この実行時ライブラリ904は、上述した実施形態の特定処理(構造化例外処理)を実行する。また、実行時ライブラリ904は、強制終了処理を実装しているとしてOS110に登録されているとする。
アプリケーション901の処理内容について説明する。アプリケーション901は、メモリ内のテーブル903に、各々の時点での自身の状態(変数の値、アドレスの戻り値等)を保持し、それを参照して処理を実施する。アプリケーション901は、クライアントからの要求を受けて、テーブル903の参照と更新を実施する。アプリケーション901は、テーブル903を更新する場合、更新の内容を共有ディスク920の更新ログファイル921に記録し、メモリのテーブル903を更新する。また、アプリケーション901は、定期的にメモリ内のテーブル903の内容を共有ディスク920内のテーブルファイル922に書き出す。
図10は、アプリケーション901の処理プログラムの例を示す図である。モジュールmodifyTableは、テーブル903の更新内容を更新ログファイル921に記録し、メモリ内のテーブル903を更新する。モジュールwriteDiskは、定期的にテーブル903の内容を共有ディスク920のテーブルファイル922に書き出し、更新ログファイル921の内容を消去する。モジュールwriteDiskの処理内容は、try文に囲まれており、finally文(テーブル903の内容の書き出し等)を定義している。
計算機900でアプリケーション901が障害のため停止すると、計算機910のクラスタ制御部915がこれを検知して、計算機910が主系となるように系切り替え処理を実施する。この中で、計算機910でアプリケーション901が起動する。アプリケーション901は、共有ディスク920からテーブル922と更新ログ921を読み取って、最新のテーブル内容を自身のメモリ内に構築してから、クライアントからの要求の受け付けを開始する。
以下、何らかの原因でアプリケーション901が不安定になり、アプリケーション901を強制停止する場合について説明する。計算機の使用者等がアプリケーション901のプロセスを強制停止するようOS100に要求すると、OS100は、アプリケーション901が実行時ライブラリ904にリンクされていることを検出して、実行時ライブラリ904の終了通知配信モジュール122を起動する。
終了通知配信モジュール122は、モジュールwriteDiskを実行しているプロセスへ割り込んで、例外処理を実行させる。この結果、モジュールwriteDiskで定義されているfinally文が実行され、通常と同じ共有ディスク920の更新処理が実行される。
この更新処理が実行された後で、計算機900のクラスタ制御部910は、計算機910に計算機900の異常を通知する。この通知により、計算機910のクラスタ制御部915が計算機900の異常を検知する。この場合、計算機910で起動するアプリケーション901は、共有ディスク920からテーブル922と更新ログファイル921を読み込むが、上述したようにテーブル922が最新の内容となっているため、計算機910におけるログファイル921を参照しての回復処理が不要となる。したがって、回復処理をしなければならない場合よりも、短時間でクライアントからの要求を受付可能となる。
このように、クラスタで実行されるアプリケーションが、上述した実施形態による構造化例外処理に対応する処理を実行時ライブラリで実行し、アプリケーションに適切な終了処理をfinally文に記述しておけば、クラスタの系切り替え処理を高速化できる。
次に、別の応用例として、第5の実施形態について説明する。この実施形態では、2台の計算機が同じ処理を並列で実行しているシステム構成において、上述した実施形態を適用する場合について説明する。
図11は、本実施形態における計算機システムの構成例を示す図である。本実施形態のシステムでは、2台の計算機1100と1110が、二重系制御モジュール1103と1113により主系と従系に構成されている。そして、これらの計算機は、クライアントとネットワークを介して接続されている。尚、本図では、計算機1100が主系であるとする。それぞれの計算機で同一のアプリケーション1101と1111が実行されており、クライアントからの要求は両方の計算機が受信して処理し、外部に影響を与える処理結果は主系の計算機1100だけが出力するよう制御されている。二重系制御モジュール1103と1113は、処理の進行状況を定期的に連絡しあい、双方の計算機の処理の進行状況を一致(同期)させている。
ここで、アプリケーション1101と1111が、上述した実施形態で説明した強制終了処理を実装している実行時ライブラリ1102と1112で実行されているとする。主系の計算機1100で実行されるアプリケーション1101は、図12に示したコードで表現されるモジュールsendLogを実行することで、処理の進行状況を従系1110に通知している。
以下、主系である計算機1100で実行されるアプリケーション1101が、障害により異常となり、プロセスの強制終了により系切り替えを実施する例を説明する。
アプリケーション1101は、上述した実施形態で説明された例外処理に対応する実行時ライブラリ1102で実行されている。このため、アプリケーション1101のプロセスを外部から強制終了すると、強制終了の通知処理の中でfinally文が実行され、モジュールsendLogによって主系の最新の処理状況が従系に通知される。この通知の後、主系の計算機1100は従系の計算機1110に異常を通知する。
一方、従系の計算機1110では、二重系制御モジュール1113が主系の異常を検知して系切り替えを行い、従系の計算機1110が主系となって処理を行う。このとき、計算機1110で実行するアプリケーションは、それまでに通知された進行状況を元に処理を引き継いで外部への出力処理を開始するが、計算機1100のアプリケーション1101の最新の処理進行状況は、強制終了の中で計算機1110に通知されているため、計算機1110は最新の状態で処理を引き継ぐことができ、短時間で処理の再開が可能となる。また、最新の情報を引継ぎができるため、古い情報に基づいて引継ぎを実施してしまう可能性を低減できる。
このように、本実施形態によれば、クラスタで実行するアプリケーションが、本発明による構造化例外処理に対応する実行時ライブラリで実行され、アプリケーションに適切な終了処理をfinally文に記述しておけば、並列二重化処理における切り替え処理を高速化でき、信頼性も向上できる。
本発明によれば、構造化例外処理の後処理の部分に、プロセス強制終了時に実施する処理を記述できる。
トランザクション、ログ、ジャーナルによって外部のプログラムで回復する場合、様々な異常の状態を想定した解析をしなければならないため、回復処理が複雑になり、処理にも長い時間がかかる。一方、本発明では、異常時の回復処理を、主たる処理の近くに記述できるため、プロセス強制終了時に必要な回復処理の記述が容易になり、かつ、その回復処理をプロセス強制終了時に実行可能となる。また、例外発生時点の状態の解析が限定されるため、回復処理も簡便になる。これにより、システムを矛盾のない状態に素早く復旧させることが可能となり、システム全体の可用性の向上が期待できる。また、ログやジャーナルといった履歴の記録も不要である。
また本発明によれば、登録されている構造化例外処理のうち、予め指定した処理だけを強制終了時に実行させるように指示できる。これにより、プロセス障害時の後始末処理を、必要な処理だけ確実に実行させることができる。これは、確実なシステム回復に繋がり、システムの可用性を向上する。また、不要な後処理を実行しないため短時間でプロセスを停止でき、システムの復旧時間を短縮できる。
更に、クラスタや並列二重処理を実施する分散計算機システムに本発明を適用すれば、強制終了時の最新の処理状況をディスクやネットワークを通じて、他の計算機に連絡できる。障害によって計算機間で処理を引き継ぐ場合に、最新の処理状況を参照して引継ぎ処理を実行できるため、引継ぎに要する時間を短縮でき、システムの可用性の向上が期待できる。また、古い処理状況に基づいて引き継ぎ処理を実施する可能性も低減できるため、システムの信頼性も向上できる。引継ぎ時間を短縮できるため、高度な応答性が要求されるシステムにおいても有効である。
200…計算機、201…CPU、202…入出力装置、203…メモリ、204…外部記憶装置、900…計算機、901…アプリケーション、905…クラスタ制御モジュール、920…共有ディスク。