MONOで実行されるハングしているアプリケーションでスレッド(スタックトレース)を表示するにはどうすればよいですか?
.NETでManagedStackExplorer(MSE)を使用してそれを実行できることを知っています。アプリケーションはMONOでのみハングするため、MONOで実行する必要があります。
または、ぶら下がっている場所を見つける方法は他にありますか?
MONOで実行されるハングしているアプリケーションでスレッド(スタックトレース)を表示するにはどうすればよいですか?
.NETでManagedStackExplorer(MSE)を使用してそれを実行できることを知っています。アプリケーションはMONOでのみハングするため、MONOで実行する必要があります。
または、ぶら下がっている場所を見つける方法は他にありますか?
WindowsではなくLinux/Unixを使用していると仮定して、プログラムにSIGQUITシグナルを送信します。これはで行うことができます
kill -QUIT $PID
ここで、$PIDはプログラムのpidです。その後、Monoはすべてのスレッドのスタックトレースをstdoutにダンプします。この後もプロセスは実行されたままですが、使用可能/安定したままであると期待するべきではないことに注意してください。
背景については、http://en.wikipedia.org/wiki/SIGQUITを参照してください。
注:スレッドダンプは、コマンドを実行したターミナルウィンドウには出力されません。kill
モノプロセスのstderrに表示されます。
GDBを使用してマネージドスタックトレースをすばやく取得することもできます。実行gdb
; ユーザーが所有するプロセスをroot化またはデバッグしていない場合は、sudoを使用してください。
mono-project.orgのMonoページのデバッグから取得した次のスクリプトを実行します。
handle SIGXCPU SIG33 SIG35 SIGPWR nostop noprint
define mono_stack
set $mono_thread = mono_thread_current ()
if ($mono_thread == 0x00)
printf "No mono thread associated with this thread\n"
else
set $ucp = malloc (sizeof (ucontext_t))
call (void) getcontext ($ucp)
call (void) mono_print_thread_dump ($ucp)
call (void) free ($ucp)
end
end
必要に応じて、これらのコマンドをにドロップして~/.gdbinit
、常にコピーして貼り付ける必要がないようにすることができます。
次に、PIDに添付します。
attach 12345
プロセス全体が一時停止されていることに注意してください。本番環境でこれを行う場合は、できるだけ高速になるようにスクリプトを作成することをお勧めします。
スタックトレースを取得するには、mono_stack
上記の定義に従って実行します。gdbではなくstdoutに出力が表示されることに注意してください。upstartを使用してプロセスを実行する場合は、upstartジョブを編集して、console log
にログインするために使用できます/var/log/upstart
。
ただし、メインスレッド以外のスレッドに興味があるかもしれません。これを行うには、実行info threads
してスレッドリストを取得thread 2
し、スレッド#2に切り替えます。スレッドのデバッグの詳細については、GDBドキュメントの複数のスレッドを使用したプログラムのデバッグを参照してください。
完了したら、を実行するquit
と、プログラムは引き続き機能します。