core

  1. コアが生成される主原因
  2. コアの解析と説明
  3. シグナルの詳細


コアが生成される主原因

プロセスがカーネルからあるシグナルを受け取って終了する場合、 システムによってプロセスのコア・イメージが書き出されます。 このコア・イメージには、レジスタの内容、プロセスの状態、 プロセスの実行時のデータなどが含まれており、 適当なデバッガを使って、それらを知ることができます。

なお、SIGXCPU/SIGXFSZ を除くこのような事象はカーネルがプロセスを監視していて、 プロセスが不正をした場合に送られます。 従ってプロセスを正しく動作するように、変更する必要があります。

SIGXCPU/SIGXFSZ は、現在ログインしているアカウントに対して設定されている、 システム資源の制限値を超えた場合に送られます。 従ってコアが書かれた原因がこの場合は、制限値を大きくする必要があります。

また実効ユーザ ID が実ユーザ ID と異なるプロセスは、 コア・イメージを生成しません。 oracle の場合、oracle のインストールユーザでないアカウントから実行し場合、 oracle のバックグランドプロセスから core は生成されません。 (oracle のバイナリは setuid プロセスです)

ulimit -a         現在の制限値を表示 

コアの解析と説明

java プログラムを実行中に、 SIGSEGV シグナルをそのプロセスに送った場合の挙動について、説明します。

[ thread dump ]

Exiting Thread (sys_thread_t:0xfefcfdb0) : no stack

Exiting Thread (sys_thread_t:0x3fec48) : no stack

Exiting Thread (sys_thread_t:0x3fea30) : no stack

Exiting Thread (sys_thread_t:0x3fe818) : no stack
"Finalizer" (TID:0x175e20, sys_thread_t:0x175d58, state:CW, thread_t: t@6,
   threadID:0xfdfc1d70, stack_bottom:0xfdfc1d70, stack_size:0x1fd70) prio=8

[1] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:146)
[2] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:168)
[3] java.lang.ref.Finalizer$FinalizerWorker$FinalizerThread.run(Finalizer.java:124)
-------------------
"Reference Handler" (TID:0x164678, sys_thread_t:0x1645b0, state:CW, thread_t: t@5,
    threadID:0xfdff1d70, stack_bottom:0xfdff1d70, stack_size:0x1fd70) prio=10

[1] java.lang.Object.wait(Object.java:424)
[2] java.lang.ref.Reference$ReferenceHandler.run(Reference.java:136)
-------------------
"Signal dispatcher" (TID:0x13b668, sys_thread_t:0x13b5a0, state:MW, thread_t: t@4,
   threadID:0xff041d70, stack_bottom:0xff041d70, stack_size:0x1fd70) prio=10

-------------------
"main" (TID:0x39400, sys_thread_t:0x39338, state:R, thread_t: t@1, threadID:0x25
228, stack_bottom:0xffbf0000, stack_size:0x800000) prio=5 *current thread*

[1] java.net.SocketInputStream.socketRead(Native Method)
[2] java.net.SocketInputStream.read(SocketInputStream.java:85)
[3] oracle.net.ns.Packet.receive(Unknown Source)
[4] oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
[5] oracle.net.ns.NetInputStream.read(Unknown Source)
[6] oracle.net.ns.NetInputStream.read(Unknown Source)
[7] oracle.net.ns.NetInputStream.read(Unknown Source)
[8] oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:717)
[9] oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:702)
[10] oracle.jdbc.ttc7.Oall7.receive(Oall7.java:361)
[11] oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1333)
[12] oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:807)
[13] oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:1685)
[14] oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1619)
[15] oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2101)
[16] oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:802)
[17] Emp.main(Emp.java:19)
-------------------
Abort (core dumped)

上記、青文字で示したとおり、main スレッド (t@1) 実行中に SIGSEGV シグナルを受けたことを示しています。

ここで status=R は、当該スレッドが実行中 (running) であったことを示し、 そのスレッド番号は t@1 です。

> dbx /usr/java1.2/jre/bin/sparc/native_threads/java core 

t@1 (l@4) シグナル ABRT (異常終了) により停止しました
0xff319780: __sigprocmask+0x0008:       jmp     %o7 + 0x8
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) where
現スレッド:     t@1

=>[1] __sigprocmask(0x0, 0xffbeca80, 0x0, 0x0, 0x0, 0x0)、アドレス 0xff319780
  [2] _resetsig(0xff31bf7c, 0x0, 0x0, 0x25228, 0xff32e000, 0x0)、アドレス 0xff30e970
  [3] _sigon(0x25228, 0xff335930, 0x6, 0xffbecb54, 0x25228, 0xff33527c)、アドレス 0xff30e110
  [4] _thrp_kill(0x0, 0x1, 0x6, 0xff32e000, 0x1, 0xff2c0450)、アドレス 0xff311150
  [5] raise(0x6, 0x0, 0x0, 0xffffffff, 0x25228, 0x0)、アドレス 0xff24ba7c
  [6] abort(0xff2bc004, 0x0, 0x0, 0x0, 0x0, 0x0)、アドレス 0xff23596c
  [7] panicHandler(0x0, 0xffbed0f8, 0xffbece40, 0xfefa9c00, 0x6, 0x0)、アドレス 0xfedaf9f0
  [8] __sighndlr(0x6, 0xffbed0f8, 0xffbece40, 0xfedae7a0, 0x252cc, 0x252bc)、アドレス 0xff31b840
  [9] sigacthandler(0x6, 0x25228, 0x0, 0x0, 0x0, 0xff32e000)、アドレス 0xff3184e0
  ---- シグナルハンドラからシグナル 6 (SIGABRT) で呼び出されました ------
  [10] __sigprocmask(0x0, 0xffbed208, 0x0, 0x0, 0x0, 0x0)、アドレス 0xff319780
  [11] _resetsig(0xff31bf7c, 0x0, 0x0, 0x25228, 0xff32e000, 0x0)、アドレス 0xff30e970
  [12] _sigon(0x25228, 0xff335930, 0x6, 0xffbed2dc, 0x25228, 0x0)、アドレス 0xff30e110
  [13] _thrp_kill(0x0, 0x1, 0x6, 0xff32e000, 0x1, 0x2bc)、アドレス 0xff311150
  [14] raise(0x6, 0x6, 0xffbed3a0, 0xfefd4de4, 0x6, 0x0)、アドレス 0xff24ba7c
  [15] abort(0xff2bc004, 0xffbed820, 0x2000, 0x60b12000, 0xb, 0xfefd5000)、アドレス 0xff23592c
  [16] __sighndlr(0xb, 0xffbed820, 0xffbed568, 0xfedae7a0, 0x252cc, 0x252bc)、アドレス 0xff31b840
  [17] sigacthandler(0xb, 0x25228, 0x0, 0x0, 0x0, 0xff32e000)、アドレス 0xff3184e0
  ---- シグナルハンドラからシグナル 11 (SIGSEGV) で呼び出されました ------
  [18] _libc_read(0x5b, 0xffbeda30, 0x8, 0x3a5a0, 0x3a588, 0x0)、アドレス 0xff29e5d4
  [19] _ti_read(0x8, 0xffbeda30, 0x8, 0x39338, 0x393b8, 0x61)、アドレス 0xff31a6d0
  [20] JVM_Read(0x8, 0xffbeda30, 0x8, 0x39338, 0xfffffffe, 0x39338)、アドレス 0xfed45630
  [21] socketReadWork(0x39520, 0x0, 0x8, 0x0, 0x0, 0xffbee2e8)、アドレス 0xfdf386b4
  [22] socketReadOnStack(0x39520, 0xffbee2e4, 0xffbee2e8, 0x0, 0x8, 0x0)、アドレス 0xfdf3877c
  [23] 0xfa448914(0xfc86a888, 0xfc1a5568, 0x0, 0x8, 0xfc1a4e98, 0xfc860be8)、アドレス 0xfa448913
  [24] 0xfa44d92c(0xfc86a888, 0xfc1a5568, 0x0, 0x8, 0x6, 0x0)、アドレス 0xfa44d92b
  [25] 0xfa44b97c(0xfc86a990, 0x0, 0xfc1a5568, 0x800, 0x3a588, 0x0)、アドレス 0xfa44b97b
  [26] 0xfa456b2c(0xfc867118, 0x109800, 0xfc1a6160, 0x3a5a0, 0x3a588, 0x0)、アドレス 0xfa456b2b
  [27] 0xfa44d71c(0xfc867118, 0xfc1a5550, 0x0, 0x1, 0x0, 0x1)、アドレス 0xfa44d71b
  [28] 0xfa450324(0xfc867118, 0xfc1a5550, 0xfc1a5520, 0x0, 0xffffffff, 0x1)、アドレス 0xfa450323
  [29] 0xfa44f380(0xfc860958, 0x0, 0x7, 0x0, 0x8, 0x0)、アドレス 0xfa44f37f
  [30] 0xfa45afb0(0xfc860be8, 0x0, 0x0, 0x0, 0xfc860958, 0x0)、アドレス 0xfa45afaf
  [31] 0xfa45a0dc(0xfc8491c0, 0xfc1a4e08, 0xfc1a4e40, 0xfc1a4e98, 0xfc1a4e98, 0xfc860be8)、アドレス 0xfa45a0db
  [32] 0xfa46e420(0xfc8491c0, 0xfc849310, 0x2, 0xfc1a0ce8, 0x0, 0x1)、アドレス 0xfa46e41f
  [33] 0xfa459ac8(0xfc843ed0, 0x0, 0xfc8491c0, 0x1, 0x20, 0xfc1a4b08)、アドレス 0xfa459ac7
  [34] 0xfa4715b0(0xfc843ed0, 0x0, 0xfc808538, 0x1, 0x2, 0xfc1a4930)、アドレス 0xfa4715af
  [35] 0xfa4703c4(0xfc843ed0, 0x0, 0x0, 0x10, 0x20, 0xfc1987b0)、アドレス 0xfa4703c3
  [36] 0xfa46f84c(0xfc843ed0, 0xfc8049b0, 0xfc843e28, 0xfa46f894, 0x0, 0xfc843ed0)、アドレス 0xfa46f84b
  [37] 0xfa42d5bc(0x327, 0xfc843e28, 0xfc843ed0, 0xfc843e28, 0x2534da, 0x0)、アドレス 0xfa42d5bb
  [38] JITInvokeCompiledMethod(0x395a4, 0x2533e0, 0x39338, 0x2533e0, 0x0, 0x0)、アドレス 0xfefb9448
  [39] invokeCompiledMethod(0xffbeebf0, 0x2533e0, 0x39338, 0x39590, 0x39590, 0x0)、アドレス 0xfecee7f8
  [40] executeJava(0x5, 0x39338, 0xfeff1a90, 0x394f4, 0x2533e0, 0xffbeefa0)、アドレス 0xfeda4cc0
  [41] runJavaMethod(0x39338, 0x39590, 0xffbeefa8, 0xeeb7a, 0x39590, 0x1)、アドレス 0xfed1bde8
  [42] jni_Invoke(0xeeb7a, 0x39590, 0x0, 0x39338, 0xffbef0ac, 0xfed1f264)、アドレス 0xfed1f740
  [43] jni_CallStaticVoidMethod(0x39520, 0x39584, 0x2533e0, 0x39338, 0x1, 0x0)、アドレス 0xfed30430
  [44] main(0x39520, 0x0, 0x3958c, 0x2533e0, 0x39584, 0x0)、アドレス 0x11998

上記緑色の部分は、java VM のシグナル・ハンドラ (シグナルが発生した場合、よびだす関数)の動作となり、 jdk の同一バージョンでは同一となります。

java VM のシグナル・ハンドラが、シグナル 11 を受けたあと、 シグナル 6 を受け取っていますが、 これは自分自身にシグナル 6 を送ってプロセスを 終了させていることを意味します。

デバッガで示されるプロセスのスタックは、main からはじまり _read (libc.so) つまり java の socketRead() 実行中にシグナル 11 を受けたことを示しています。

従ってもし実行中にいずれかの不具合でコアをはいた場合は、 緑色の部分を除くはじめの関数が SIGSEGV を起こした関数です。

シグナルの詳細

4.3BSD および SVR のシグナルでデフォルトでコア・イメージを生成させるシグナルは、 以下のとおりです。

AIX や Linux などでは、シグナルの値や終了値に多少の違いがあります。
solaris、HP-UX、AIXは /usr/include/sys/signal.h を、 Linux は /usr/include/asm/signal.h を参照ください。

シグナル名 原    因 終了値 注1 注2 注3
SIGQUIT 3実行中止 131 *

SIGILL 4不正命令 132 ***
SIGTRAP 5トレース・ブレークポイント・トラップ 133


SIGABRT 6アボート 134


SIGEMT 7エミュレーション・トラップ 135 *
-
SIGFPE 8算術例外 136
**
SIGBUS 10バス・エラー 138 ***7:135
SIGSEGV 11セグメント・エラー 139
**
SIGSYS 12システム・コール不正 140 ***-
SIGXCPU 30CPU 時間が制限を越えました 158 *
24:152
SIGXFSZ 31ファイル・サイズが制限を越えました 159 *
25:153

注1: linux では core を作りません。
注2: プログラムに問題がある場合に、システムから該当プロセスに送られる
シグナルで、core が作られ、実行は強制終了させられます。
注3: linux はシグナルの値と終了値が違います。
また、存在しない場合は - です。

外部から core を生成させるには、まずそのプロセスの PID を取得し以下のようにします。

 > kill -シグナル番号 PID

  ただし、シグナル番号は上記の 1 つです。

【 関連項目 】 (solaris)

core(4),signal(2),signal(5),file(1)

【 関連リンク 】