UNIX環境などで2038年1月19日以降になると、システムが正常に動作しなくなるという「西暦2038年問題」が、本来より34年も早い2004年1月10日に突然、現実になった。プログラムの設定ミスで、コンピュータが正しい時刻を認識できなくなるトラブルが、KDDIをはじめとする企業で続発した。

図1●今年に西暦2038年問題が表面化した理由
表●西暦2038年問題あるいはそれに類似したトラブルが起きた事例
図2●KDDIのシステムでは1月10日を境に、料金算出に使う時刻が過去の日時になった
KDDIのシステムは0.5秒単位で経過時間を取得しているため、1970年と2038年の真ん中に当たる1月10日に桁あふれを起こした

 今年1月10日は、UNIXの内部時間がスタートする1970年1月1日と、コンピュータの「西暦2038年問題」が起こる2038年1月19日のちょうど中間の日付に当たる(図1[拡大表示])。1月10日には、KDDIなどさまざまな企業で西暦2038年問題に起因するプログラムの不具合や、その“亜種”とも言うべきトラブルが続発した。表にあるように、不具合が判明した事例だけで六つある。

 西暦2038年問題とは、UNIX環境などで協定世界時(UTC)の2038年1月19日3時14分8秒を過ぎると、システムが正しく時刻を認識できなくなることを指す。2038年1月19日になって、1970年1月1日からの経過秒数が約21億秒を超えると、コンピュータが認識できる経過秒数の桁数を超えてしまう。その結果、コンピュータはプログラムに間違った経過秒数を返すことになり、これが不具合につながる(2038年問題については15ページの別掲記事を参照)。

 2038年まで起こらないはずの不具合が、1月10日に顕在化した背景にあるのは、プログラミング時の人為的なミスと、それを発見できなかったチェック漏れだ。実際の不具合にはいくつかのパターンが見いだせる。インターネットイニシアティブ(IIJ)や日本IBM、システム・インテグレータのトパックスは自社製品で、桁あふれを考慮せずに2種類の経過秒数を足し合わせる処理を行った。ポータル・サイトのgooを運営するNTT-X(4月1日からはNTTレゾナントに運営が移行)やKDDI、CADソフト大手のPTCジャパンなどは、プログラミングの際に経過秒数の最大桁数を間違えて設定した。最大桁数を1桁間違えると、1970年と2038年の中間に当たる2004年1月10日で桁あふれが起きてしまう。

システムの内部時計が69年前の日時に

 「いわゆる“西暦2038年問題”が原因だ」。KDDIは3月5日、国内電話サービスの料金を誤って請求した原因について、本誌にこうコメントした。誤請求が生じたのは1月10日から2月25日に利用した通話の一部。影響範囲は通話数にして4万5866件、総額は約1346万円分におよぶ。

 誤請求が発覚したきっかけは、2月19日にユーザーから「利用料金がおかしい」という指摘があったこと。これを受けて同社は調査を開始し、2月24日に通話料金の課金システムの一部に不具合があることを見つけた。

 不具合が起きた課金システムでは、今年の1月10日を超えると、実際の日付とシステム上の日付にずれが生じた。システム上の日付が1935年に戻ってしまい、曜日も実際とは異なる曜日に変わった(図2[拡大表示])。時間当たりの通話料金は休日か平日かによって変わるため、料金を計算する際には通話時の日付と曜日が重要となる。日付を正確にカウントできなくなったことで、割安な休日料金を適用すべき土日祝日の通話に割高な平日料金で課金したり、逆に平日の通話に割安な休日料金で課金したりしていた。

 ではなぜ、2038年までは起こらないはずの問題が起こったのか。KDDIの主なシステムは、0.5秒単位で時刻を認識している。そのため、1秒単位で時刻を認識する一般的なシステムの半分の時間しか経過秒数を保持できない。にもかかわらず、このシステムでは、利用可能な最大桁数を増やす設定にしていなかった。

不具合は通信プログラムに集中

 そのほかの事例は、何らかの通信に関連して問題が起こることが多かった。IIJのルーター、日本IBMやトパックスのミドルウエア、PTCジャパンのソフトでは、他の機器やアプリケーションと通信しようとした際に、ソフトが正常に動作しなくなることがあった。

 IIJのルーター「SEIL/neu」シリーズの一部機種では、NTP(Network Time Protocol)を使って、ネットワーク上にあるNTPサーバーから時刻を取得する設定にしていると、不具合が起きる可能性があった。IIJは1月13日にユーザーから指摘を受けて、不具合の存在を知った。同社は緊急に対策を講じ、翌日には不具合を修正するファームウエアの配布を開始した。

 ファームウエアを修正しない場合、ルーターを再起動した場合などに内部時刻が1935年の間違った日付になる。具体的には、通信経路を動的に設定する機能が正常に動作しなくなり、この機能を使って設定した通信先と通信ができなくなるなどの不具合が起こることがある。どの程度の影響があったかは、「SEILの利用者数は非公開」(IIJ)としているため不明である。

 KDDIの次に影響が大きかったのは、1月11日に20行以上の銀行でATM(現金自動預け払い機)が一部正常に利用できなくなった事象である(本誌2004年2月9日号22~25ページ参照)。いくつかの銀行では1月11日9時ごろからトラブルを確認していたが、原因がなかなかつかめなった。

 同日午後になってトラブルの原因が、他行との通信を中継する「対外系システム」で利用する日本IBMのソフト「FINEACE/6000」関連の不具合であることが判明。一部のプログラムで正常な日時を取得できなくなった結果、本来は正常な通信データをタイムアウトと誤認して、トラブルにつながった。日本IBMは、17時から各行の対外系システムに修正プログラムを適用。1月12日1時には、各行のシステムが問題なく動作することを確認した。

ユーザーへの周知を徹底し危機回避

 他社と異なりPTCジャパンは、昨年12月10日に、米国本社が1月10日から顕在化する不具合があることを発見した。不具合が見つかったのは同社のCADソフト「Pro/ENGINEER」と関連ソフト。1月10日を過ぎると、これらのソフト間で通信ができなくなる可能性があった。同社の北村守東日本営業統括本部統括本部長は、「3500社に3万人いるユーザーのうちの7割から8割が、この不具合の影響を受ける恐れがあった」と話す。

 12月15日に米国本社から連絡を受けた同社は、12月16日にさっそく対策チームを編成。ユーザーへの不具合の周知や、修正プログラムの配布を徹底する取り組みを開始した。北村本部長は、「サポート窓口も開設し、全部で200件以上の問い合わせを受けた。ただし、1月10日以降に実際に不具合が起きたという連絡は数件しかなかった」という。

「西暦2038年問題」はなぜ起こるか

図A●「西暦2038年問題」で起きる事象

 「西暦2038年問題」とは、Linuxを含むUNIX環境やC/C++言語で記述したプログラムで、協定世界時(UTC)の2038年1月19日3時14分8秒を過ぎると、システムが正しく時刻を認識できなくなることをいう。UNIXはシステム内部の時刻を、1970年1月1日0時0分0秒(UTC)からの経過秒数で保持している。経過秒数を表す時刻データには、32ビットの符号付き整数を使っている。先頭の1ビットは正負の符号を表すために使い、2の31乗までの秒数(約21億秒)しか認識できない(図A[拡大表示])。

 経過秒数が2の31乗秒を超えるのが2038年1月19日3時14分8秒(UTC)なのだ。経過秒数が2の31乗秒を超えると、時刻データの先頭ビットに「1」が立つ。そして、先頭ビットの「1」は負の値であることを意味する。2の31乗秒を超えた後は、内部時刻は1901年12月13日(UTC)に戻ってしまう。そうなると、システムの時刻表示がおかしくなるだけでなく、処理に時刻データが必要なプログラムで不具合が起きることがある。

 西暦2038年問題を回避するための方法はいくつかある。代表的なものとしてUNIX環境の場合は64ビットOSを利用する方法がある。C/C++言語を使ってプログラミングする際には、時刻を取得するときに32ビット以上の整数を使えるようにすればよい。

 ただしその場合は、時刻を取得する際に多く使っている「time_t」変数の整数型の定義を変更しなければならない、もしくは別に時刻を取得するプログラムを作る必要がある。ANSI(米国規格協会)規格のtime_t変数は実装する際に、32ビットの符号付き整数になっていることが一般的だからだ。


(鈴木 孝知、中村 建助)