プロセスがカーネルからあるシグナルを受け取って終了する場合、 システムによってプロセスのコア・イメージが書き出されます。 このコア・イメージには、レジスタの内容、プロセスの状態、 プロセスの実行時のデータなどが含まれており、 適当なデバッガを使って、それらを知ることができます。
なお、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 | 30 | CPU 時間が制限を越えました | 158 | * | 24:152 | |
SIGXFSZ | 31 | ファイル・サイズが制限を越えました | 159 | * | 25:153 |
注1: | linux では core を作りません。 |
---|---|
注2: | プログラムに問題がある場合に、システムから該当プロセスに送られる
シグナルで、core が作られ、実行は強制終了させられます。 |
注3: | linux はシグナルの値と終了値が違います。 また、存在しない場合は - です。 |
外部から core を生成させるには、まずそのプロセスの PID を取得し以下のようにします。
> kill -シグナル番号 PID ただし、シグナル番号は上記の 1 つです。