ソフトウェア開発や運用において、プロセスがフリーズする状況に遭遇することがあります。この状況はシステムパフォーマンスの低下やサービス停止を引き起こす可能性があります。本稿では、pstackツールを使用してプロセスフリーズの問題をトラブルシューティングする方法について説明します。プロセスのスタック情報を分析することで、問題の原因を特定し解決策を見つけます。
風控システムの子サービスが応答停止し、風控サービスが利用不能に。サービス可用性モニタリングの不足により、プロセス応答停止をタイムリーに検知できず、システムが利用不能となった。
正文
プロセスデッドロックとは、プロセスが応答しなくなるものの、終了しない状態を指します。これは、デッドロック、リソース枯渇、例外など、様々な原因で発生する可能性があります。このような問題を解決するためには、pstackツールを使用してプロセスのスタック情報を分析し、問題の根本原因を特定することができます。
手順
pstack は、一般的に gdb(GNU デバッガー)と共に提供される便利なツールです。以下のコマンドでインストールできます。
sudo apt-get install gdb
プロセスIDの取得:まず、スリープ状態のプロセスのプロセスID(PID)を取得する必要があります。psコマンドを使用して、すべてのプロセスをリストし、調査対象のプロセスIDを見つけます。 pstack ツールを使用してプロセススタックを解析します。プロセス ID を取得したら、pstack ツールでそのプロセスのスタック情報を入手できます。以下のコマンドを実行してください:
pstack <PID>
このプロセスが実行中の関数呼び出しシーケンスを表示し、スタック情報を出力します。これらの情報から、プロセスの停止位置を特定し、問題の箇所を突き止めることができます。
スタック情報を解析することで、プロセスの応答なしの原因を特定できます。デッドロックや無限ループ、その他の異常が発見される可能性があります。状況に応じて、ロックの解放やコードロジックの修正などの対応策を講じてください。
事例
簡単なデモで、メイン関数起動後、新しいスレッドを作成し、実際の実行関数が無限ループに入り、プログラムが正常に終了せず、フリーズした状態になる。
cmake_minimum_required(VERSION 3.0.0)
project(pstack_main VERSION 0.1.0 LANGUAGES C CXX)
include(CTest)
enable_testing()
# 查找线程库
find_package(Threads REQUIRED)
add_executable(pstack_main main.cpp)
# 链接线程库
target_link_libraries(pstack_main PRIVATE Threads::Threads)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
#include <iostream>
#include <thread>
#include <chrono>
void infiniteLoop() {
while (true) {
// 主线程进入死循环
}
}
int main() {
std::thread thread(infiniteLoop); // 创建一个线程,执行死循环函数
thread.join(); // 等待线程结束
return 0;
}
プログラム起動、pstack結果:
Thread 2 (Thread 0x7eff3619b700 (LWP 1315017)):
#0 infiniteLoop () at /root/pstack/main.cpp:6
#1 0x0000000000402ca9 in std::__invoke_impl<void, void (*)()> (__f=@0x2260eb8: 0x4029a6 <infiniteLoop()>) at /usr/include/c++/8/bits/invoke.h:60
#2 0x0000000000402b02 in std::__invoke<void (*)()> (__fn=@0x2260eb8: 0x4029a6 <infiniteLoop()>) at /usr/include/c++/8/bits/invoke.h:95
#3 0x0000000000403150 in std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul> (this=0x2260eb8) at /usr/include/c++/8/thread:244
#4 0x0000000000403126 in std::thread::_Invoker<std::tuple<void (*)()> >::operator() (this=0x2260eb8) at /usr/include/c++/8/thread:253
#5 0x000000000040310a in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run (this=0x2260eb0) at /usr/include/c++/8/thread:196
#6 0x00007eff36bceb23 in execute_native_thread_routine () from /lib64/libstdc++.so.6
#7 0x00007eff36ea91ca in start_thread () from /lib64/libpthread.so.0
#8 0x00007eff361d58d3 in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7eff372e1740 (LWP 1315016)):
#0 0x00007eff36eaa6cd in __pthread_timedjoin_ex () from /lib64/libpthread.so.0
#1 0x00007eff36bceda7 in std::thread::join() () from /lib64/libstdc++.so.6
#2 0x00000000004029d2 in main () at /root/pstack/main.cpp:13
確認できるところによると、プロセスのフリーズの原因は無限ループです。メインスレッドが無限ループに入り、サブスレッドが終了できず、結果としてプロセスがフリーズします。