commit
cc7ec9f435
|
@ -9,20 +9,16 @@ deadlock-detect 用于C/C++/Java进程的死锁检测分析,帮助开发者在
|
|||
|
||||
## 功能
|
||||
- 进程死锁检测
|
||||
- 远程环境进程死锁检测
|
||||
|
||||
## 使用方法
|
||||
#### 检查依赖
|
||||
依赖binutils、libc-bin、sshpass、libc6-dbg软件包
|
||||
安装方式```sudo apt install binutils libc-bin gdb sshpass libc6-dbg -y```
|
||||
依赖binutils、libc-bin、libc6-dbg软件包
|
||||
安装方式```sudo apt install binutils libc-bin gdb libc6-dbg -y```
|
||||
或 通过插件依赖管理器extension-dependency进行依赖检测与安装
|
||||
|
||||
#### 进程死锁检测
|
||||
执行ctrl+shift+p启动命令面板或者在编辑区域点击鼠标右键选择'C/C++/Java进程死锁检测',选择`C/C++/Java进程死锁检测`,默认会打开一个页面,按要求选择死锁类型、添加`进程Pid`、`用户密码`即可。
|
||||
|
||||
#### 远程环境死锁检测
|
||||
执行ctrl+shift+p启动命令面板或者在编辑区域点击鼠标右键选择'C/C++/Java进程死锁检测',选择`C/C++/Java进程死锁检测`,默认会打开一个页面,点击“远程检测”,按要求添加`进程Pid`、`远程用户`、`远程IP地址`、`远程登录密码`即可。
|
||||
|
||||
# C/C++/Java Process deadlock analysis
|
||||
|
||||
## Introduction
|
||||
|
@ -31,7 +27,6 @@ deadlock-detect is a tool for deadlock detection and analysis in C/C++/Java proc
|
|||
|
||||
## Features
|
||||
- Process deadlock detection
|
||||
- Remote environment process deadlock detection
|
||||
|
||||
## Usage
|
||||
#### Check dependencies
|
||||
|
@ -40,6 +35,4 @@ deadlock-detect is a tool for deadlock detection and analysis in C/C++/Java proc
|
|||
#### Process deadlock detection
|
||||
Open the command palette with ctrl+shift+p or right-click in the editor area and select C/C++/Java Process Deadlock Detection. Select C/C++/Java Process Deadlock Detection, and a page will open. Choose the type of deadlock, add the process PID, and >user password as required.
|
||||
|
||||
#### Remote environment deadlock detection
|
||||
Open the command palette with ctrl+shift+p or right-click in the editor area and select C/C++/Java Process Deadlock Detection. Select C/C++/Java Process Deadlock Detection, and a page will open. Click "Remote Detection" and add the process PID, remote user, remote IP address, and remote login password as required.
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/sh
|
||||
DEADLOCK_BEGIN_FLAG='^Found .* Java-level deadlock'
|
||||
DEADLOCK_END_FLAG='^Java stack information for the threads .*'
|
||||
|
||||
SEM_WAIT_FLAG='parking to wait for.*Semaphore$.*'
|
||||
|
||||
STACK_INFO=`jstack $1`
|
||||
|
||||
MUTEXLOCK=`echo "$STACK_INFO" | grep "java.util.concurrent.locks.ReentrantLock.*"`
|
||||
RWLOCK=`echo "$STACK_INFO" | grep "java.util.concurrent.locks.ReentrantReadWriteLock.*"`
|
||||
SEMLOCK=`echo "$STACK_INFO" | grep "java.util.concurrent.Semaphore.*"`
|
||||
|
||||
if [ $2 -eq 1 ];then
|
||||
# 信号量
|
||||
[ -z "$SEMLOCK" ] && exit 0
|
||||
fi
|
||||
|
||||
if [ $2 -eq 2 ];then
|
||||
# 互斥锁
|
||||
[ -z "$MUTEXLOCK" ] && exit 0
|
||||
fi
|
||||
|
||||
if [ $2 -eq 3 ];then
|
||||
# 读写锁
|
||||
[ -z "$RWLOCK" ] && exit 0
|
||||
fi
|
||||
|
||||
|
||||
BEGIN=`echo "$STACK_INFO" | grep -n -E "${DEADLOCK_BEGIN_FLAG}"`
|
||||
END=`echo "$STACK_INFO" | grep -n -E "${DEADLOCK_END_FLAG}"`
|
||||
DEADLOCK_STATUS=0
|
||||
[ -n "$BEGIN" ] && [ -n "$END" ] && DEADLOCK_STATUS=1
|
||||
DETAIL_INFO=''
|
||||
|
||||
# mythread1 waiting for ownable synchronizer 0x0000000717159f08 which is held by mythread2
|
||||
getAThreadHoldInfo(){
|
||||
[ ! $# -eq 3 ] && return
|
||||
echo "$1|$2|$3"
|
||||
}
|
||||
|
||||
if [ $DEADLOCK_STATUS -eq 1 ];then
|
||||
# 死锁
|
||||
DEADLOCK_BEGIN_LINE_NUM=`echo "$BEGIN" | awk -F ':' '{print $1}' | head -n 1`
|
||||
DEADLOCK_END_LINE_NUM=`echo "$END" | awk -F ':' '{print $1}' | head -n 1`
|
||||
BEGIN_NUM=$(expr $DEADLOCK_BEGIN_LINE_NUM + 1)
|
||||
END_NUM=$(expr $DEADLOCK_END_LINE_NUM - 1)
|
||||
DETAIL_INFO=$(echo "${STACK_INFO}" | sed -n "${BEGIN_NUM},${END_NUM}p" | grep -v -E "^==" | sed -e 's/(.*)\|[,:"]//g' | grep -v '^$' 2>/dev/null)
|
||||
if [ -n "$DETAIL_INFO" ];then
|
||||
num=1
|
||||
echo "$DETAIL_INFO" | while IFS= read -r line; do
|
||||
[ $(expr $num % 3) -eq 1 ] && threadID=$line
|
||||
[ $(expr $num % 3) -eq 2 ] && mutexID=`echo $line | grep -o '0x[0-9a-fA-F]*'`
|
||||
[ $(expr $num % 3) -eq 0 ] && heldThreadID=`echo $line | sed -e 's/which is held by//g'` && getAThreadHoldInfo $threadID $mutexID $heldThreadID
|
||||
num=$(expr $num + 1)
|
||||
done
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 信号量死锁
|
||||
SEM_INFOS=`echo "${STACK_INFO}" | grep -n "$SEM_WAIT_FLAG"`
|
||||
echo "$SEM_INFOS" | while IFS= read -r line; do
|
||||
lnum=`echo $line | awk -F ':' '{print $1}'`
|
||||
mutexid=`echo $line | grep -o '0x[0-9a-fA-F]*'`
|
||||
threadinfo=`echo "${STACK_INFO}" | sed -n "$(expr $lnum - 3)p"`
|
||||
[ -n "${threadinfo}" ] && echo "${threadinfo} ${mutexid}" | awk '{print $1"|"$NF}' | sed -e 's/"//g'
|
||||
done
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/sh
|
||||
|
||||
if test $# -ne 1; then
|
||||
echo "Usage: `basename $0 .sh` <process-id>" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test ! -r /proc/$1; then
|
||||
echo "Process $1 not found." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# GDB doesn't allow "thread apply all bt" when the process isn't
|
||||
# threaded; need to peek at the process to determine if that or the
|
||||
# simpler "bt" should be used.
|
||||
|
||||
backtrace="bt"
|
||||
if test -d /proc/$1/task ; then
|
||||
# Newer kernel; has a task/ directory.
|
||||
if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
|
||||
backtrace="thread apply all bt"
|
||||
fi
|
||||
elif test -f /proc/$1/maps ; then
|
||||
# Older kernel; go by it loading libpthread.
|
||||
if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
|
||||
backtrace="thread apply all bt"
|
||||
fi
|
||||
fi
|
||||
|
||||
GDB=${GDB:-/usr/bin/gdb}
|
||||
|
||||
# Run GDB, strip out unwanted noise.
|
||||
# --readnever is no longer used since .gdb_index is now in use.
|
||||
$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
|
||||
set width 0
|
||||
set height 0
|
||||
set pagination no
|
||||
$backtrace
|
||||
EOF
|
||||
/bin/sed -n \
|
||||
-e 's/^\((gdb) \)*//' \
|
||||
-e '/^#/p' \
|
||||
-e '/^Thread/p'
|
|
@ -3,7 +3,7 @@
|
|||
"displayName": "deadlock-detect",
|
||||
"description": "Deadlock detect for C/C++/Java program.",
|
||||
"publisher": "KylinIDETeam",
|
||||
"version": "0.2.7",
|
||||
"version": "0.2.8",
|
||||
"engines": {
|
||||
"vscode": "^1.54.0"
|
||||
},
|
||||
|
|
|
@ -153,7 +153,14 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
function gdb_cmdof_info_thread(pwd:string,pid:string):string[]{
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "q" `;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "q" `;
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString()
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
//console.log("BBBB:",cmdout)
|
||||
let infothreads = cmdout.trim().split('\n')
|
||||
//console.log("CCCC:",infothreads)
|
||||
|
@ -205,6 +212,9 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
lwp = key;
|
||||
thread_id = lwp_to_thread_id[key];
|
||||
let bt_output = gdb_cmdof_thread_n_and_bt(pwd,pid,thread_id);
|
||||
if(bt_output.length === 0){
|
||||
return [];
|
||||
}
|
||||
for(let j=0;j<bt_output.length;j++){
|
||||
if(bt_output[j].startsWith("#") && bt_output[j].includes(armRpmMutexlock))
|
||||
{
|
||||
|
@ -263,7 +273,8 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
if(lockID !="unknown"){
|
||||
lockowner = gdb_cmdof_p_mutex_owner_for_loongarchServer(pwd,pid,thread_id,lockID);
|
||||
}else{
|
||||
lockowner = "unknown"
|
||||
lockowner = "unknown";
|
||||
return [];
|
||||
}
|
||||
|
||||
const mutexlock_info_temp:rwlock_infomation={
|
||||
|
@ -351,6 +362,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
};
|
||||
thread_RWlock_info.push(mutexlock_info_temp)
|
||||
}else{
|
||||
return [];
|
||||
console.log('No rwlock address found for armserver');
|
||||
}
|
||||
}
|
||||
|
@ -382,6 +394,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
};
|
||||
thread_RWlock_info.push(mutexlock_info_temp)
|
||||
}else{
|
||||
return [];
|
||||
console.log('No rwlock address found for armserver');
|
||||
}
|
||||
}
|
||||
|
@ -414,6 +427,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
thread_RWlock_info.push(mutexlock_info_temp)
|
||||
}else{
|
||||
console.log('No rwlock address found for armserver');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +468,12 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
function gdb_cmdof_thread_n_and_bt(pwd:string,pid:string,thread_id:string):string[]{
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "bt" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "bt" -ex "q"`;
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return [];
|
||||
}
|
||||
|
||||
let bt_output = cmdout.trim().split('\n');
|
||||
return bt_output;
|
||||
|
@ -463,7 +482,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$x6" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$x6" -ex "q"`;
|
||||
//console.log("execcmd is:",temcmd)
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
//arm服务器锁地址存放在寄存器x6
|
||||
let x6_output = cmdout.trim().split('\n');
|
||||
//console.log("x6_output is:",x6_output)
|
||||
|
@ -484,7 +509,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$rbx" -ex "q"`;
|
||||
let temcmd = ` echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$rbx" -ex "q"`;
|
||||
//console.log("execcmd is:",temcmd)
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
//x86服务器锁地址存放在寄存器rbx
|
||||
let x6_output = cmdout.trim().split('\n');
|
||||
//console.log("x6_output is:",x6_output)
|
||||
|
@ -506,7 +537,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$a6" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$a6" -ex "q"`;
|
||||
//console.log("execcmd is:",temcmd)
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
//x86服务器锁地址存放在寄存器rbx
|
||||
let x6_output = cmdout.trim().split('\n');
|
||||
//console.log("x6_output is:",x6_output)
|
||||
|
@ -528,7 +565,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$s0" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p/x \\$s0" -ex "q"`;
|
||||
//console.log("execcmd is:",temcmd)
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
//loongarch服务器锁地址存放在寄存器s0
|
||||
let s0_output = cmdout.trim().split('\n');
|
||||
//console.log("s0_output is:",s0_output)
|
||||
|
@ -553,7 +596,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p ${printName}" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p ${printName}" -ex "q"`;
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
|
||||
//arm服务器锁owner
|
||||
let owner_output = cmdout.trim().split('\n');
|
||||
|
@ -579,7 +628,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p ${printName}" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "thread ${thread_id}" -ex "p ${printName}" -ex "q"`;
|
||||
let cmdout = execSync(temcmd).toString();
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString();
|
||||
}catch(error){
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
|
||||
//arm服务器锁owner
|
||||
let owner_output = cmdout.trim().split('\n');
|
||||
|
@ -601,7 +656,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
let mutex_owner= lockname +"._M_mutex.__data.__owner"
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "p ${mutex_owner}" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "p ${mutex_owner}" -ex "q"`;
|
||||
let cmdout = execSync(temcmd).toString()
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString()
|
||||
}catch(error){
|
||||
return "unknow";
|
||||
}
|
||||
|
||||
let mutex_info = cmdout.trim().split('\n');
|
||||
for(let j=mutex_info.length-1;j>=0;j--){
|
||||
if(mutex_info[j].startsWith("$1")){
|
||||
|
@ -618,7 +679,13 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
let mutex_owner= lockname +".__data.__cur_writer"
|
||||
//let temcmd = `cat ${__dirname}/../detect-tools/.user.pwd | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "p ${mutex_owner}" -ex "q"`;
|
||||
let temcmd = `echo "${pwd}" | sudo -S gdb -q -p ${pid} -ex "info threads" -ex "thread ${thread_id}" -ex "p ${mutex_owner}" -ex "q"`;
|
||||
let cmdout = execSync(temcmd).toString()
|
||||
let cmdout = "".toString();
|
||||
try{
|
||||
cmdout = execSync(temcmd).toString()
|
||||
}catch(error){
|
||||
return "unknow";
|
||||
}
|
||||
|
||||
let mutex_info = cmdout.trim().split('\n');
|
||||
for(let j=mutex_info.length-1;j>=0;j--){
|
||||
if(mutex_info[j].startsWith("$1")){
|
||||
|
@ -768,6 +835,14 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//ARM x86 loongarch64 服务器
|
||||
let mutex_info:rwlock_infomation[] = [];
|
||||
let info_threads = gdb_cmdof_info_thread(form.pwd,form.pid);
|
||||
//gdb error 进程终止
|
||||
if(info_threads.length === 0){
|
||||
form.mutexflag = false;
|
||||
form.errflag = "gdberror";
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
let lwp_to_thread_id = get_threadid_lwp_relation_for_armServer(info_threads);
|
||||
if(form.dead_type == 1){
|
||||
if(arch == "loongarch64" || arch == "loong64" || arch =="la64"){
|
||||
|
@ -775,6 +850,14 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
}else{
|
||||
//arm服务器系统互斥锁寄存器为x4(或者x19),但是不需要安装glibc-debugutils,gdb调试包含锁信息
|
||||
mutex_info = judge_mutex(form.pwd,form.pid,lwp_to_thread_id,"__gthread_mutex_lock");
|
||||
//gdberror导致获取mutex_info为空
|
||||
if(mutex_info.length === 0){
|
||||
form.mutexflag = false;
|
||||
form.errflag = "gdberror";
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("mutex_info is:",mutex_info)
|
||||
if(mutex_info.length != 0){
|
||||
|
@ -859,9 +942,27 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
}else if(form.dead_type == 1 && isOpenkylin == true && arch =="x86_64"){
|
||||
//openkylin && x86
|
||||
let info_threads = gdb_cmdof_info_thread(form.pwd,form.pid);
|
||||
//gdb error 进程终止
|
||||
if(info_threads.length === 0){
|
||||
form.openkylin = true;
|
||||
form.mutexflag = false;
|
||||
form.errflag = "gdberror";
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
let lwp_to_thread_id = get_threadid_lwp_relation(info_threads);
|
||||
//let mutex_info = judge_mutex(form.pid,lwp_to_thread_id,"__GI___lll_lock_wait");
|
||||
let mutex_info = judge_mutex(form.pwd,form.pid,lwp_to_thread_id,"___pthread_mutex_lock");
|
||||
//gdberror导致获取mutex_info为空
|
||||
if(mutex_info.length === 0){
|
||||
form.mutexflag = false;
|
||||
form.openkylin = true;
|
||||
form.errflag = "gdberror";
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
if(mutex_info.length !=0){
|
||||
form.openkylin = true;
|
||||
form.mutexflag = true;
|
||||
|
@ -881,6 +982,14 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
}else if((form.dead_type == 2 || form.dead_type == 3) && sys_flag == "deb" ){
|
||||
//x86 arm loongarch桌面系统读写锁和信号量
|
||||
let info_threads = gdb_cmdof_info_thread(form.pwd,form.pid);
|
||||
//gdb error 进程终止
|
||||
if(info_threads.length === 0){
|
||||
form.rwflag = false;
|
||||
form.errflag = "gdberror";
|
||||
panel.webview.postMessage({
|
||||
res: form});
|
||||
return;
|
||||
}
|
||||
let lwp_to_thread_id = get_threadid_lwp_relation(info_threads);
|
||||
if(form.dead_type == 2){
|
||||
//loongarch桌面系统读写锁寄存器和服务器系统一致a6,用读寄存器方式实现,不需要安装libc6-dbg
|
||||
|
@ -890,6 +999,8 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
rwlock_info = judge_rwlock_for_armServer(form.pwd,form.pid,lwp_to_thread_id,"pthread_rwlock_");
|
||||
}else if(arch == "loongarch64" || arch == "loong64" || arch =="la64"){
|
||||
rwlock_info = judge_rwlock_for_loongarchServer(form.pwd,form.pid,lwp_to_thread_id,"pthread_rwlock_");
|
||||
}else{
|
||||
rwlock_info = judge_rwlock_for_x86Server(form.pwd,form.pid,lwp_to_thread_id,"pthread_rwlock_");
|
||||
}
|
||||
|
||||
if(rwlock_info.length != 0){
|
||||
|
@ -1087,7 +1198,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
//执行死锁检测程序
|
||||
let isJava = isJavaProcess(form.pid)
|
||||
if(isJava){
|
||||
child.exec(`jstack ${form.pid}`, (e1, x, c2) => {
|
||||
child.exec(`${__dirname}/../detect-tools/detect_java.sh ${form.pid} ${form.deadType}`, (e1, x, c2) => {
|
||||
console.log("output is:",x)
|
||||
form.arch=os.arch();
|
||||
form.data =x;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,34 +47,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--el-tab-pane label="C/C++远程检测" name="second" >
|
||||
<div style="width: 60%;margin:auto">
|
||||
<br />
|
||||
<el-input v-model="remote_pid_input" placeholder="请输入被检测进程PID"></el-input>
|
||||
<br />
|
||||
<el-input v-model="remote_addr_input" placeholder="请输入远程IP地址"></el-input>
|
||||
<el-input v-model="remote_account_input" placeholder="请输入远程用户账号"></el-input>
|
||||
<el-input placeholder="请输入远程用户密码" v-model="remote_passwd_input" show-password></el-input>
|
||||
<br /> <br />
|
||||
<el-button type="primary" @click="begin_remote_check()">开始检测</el-button>
|
||||
</div>
|
||||
<br />
|
||||
<el-card class="box-card" style="width: 80%;margin: auto;">
|
||||
<div>
|
||||
<span>线程死锁关系:</span>
|
||||
<br>
|
||||
<span>{{ remote_thread_data }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card id="main_remote" style="width: 80%; height: 400px; margin: auto;"></el-card>
|
||||
</el-tab-pane>
|
||||
<div class="loading-overlay" v-if="this.loading2">
|
||||
<div class="loading-spinner">
|
||||
<div class="text1">检测中<span class="dots">...</span></div>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<el-tab-pane label="Java进程死锁检测" name="third" >
|
||||
<div style="width: 60%;margin:auto">
|
||||
<br />
|
||||
|
@ -118,14 +90,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</el-tabs>
|
||||
|
||||
<!--div class="loading-overlay" v-if="this.loading1">
|
||||
<div class="loading-spinner">
|
||||
<div class="text1">检测中<span class="dots">...</span></div>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -309,6 +273,8 @@ export default {
|
|||
message:'待检测进程不是C/C++类型,请重新输入!',
|
||||
});
|
||||
}else{
|
||||
this.local_thread_data = ''
|
||||
this.thread_info = []
|
||||
if(this.c_dead_type == 3){
|
||||
this.loading1 = false;
|
||||
if(event.data.res.wrongpasswd == true){
|
||||
|
@ -401,7 +367,16 @@ export default {
|
|||
let temp_array_copy2 = []
|
||||
let flag = true;
|
||||
|
||||
console.log("发现读写锁死锁:",event.data.res.thread_rwlock_info)
|
||||
console.log("发现读写锁死锁:",event.data.res.thread_rwlock_info);
|
||||
let tmpArr = [];
|
||||
let tmpObjArr = [];
|
||||
event.data.res.thread_rwlock_info.forEach((item)=>{
|
||||
if(!tmpArr.includes(item.threadID)){
|
||||
tmpArr.push(item.threadID);
|
||||
tmpObjArr.push(item);
|
||||
}
|
||||
})
|
||||
event.data.res.thread_rwlock_info = tmpObjArr;
|
||||
for(let i=0;i<event.data.res.thread_rwlock_info.length;i++){
|
||||
let obj = {};
|
||||
let threadLwp = event.data.res.thread_rwlock_info[i]
|
||||
|
@ -533,7 +508,7 @@ export default {
|
|||
/* */
|
||||
if(cirle_deadlock){
|
||||
this.$message({
|
||||
message: "发现互斥锁死锁(严格意义的环路死锁)!",
|
||||
message: "2发现互斥锁死锁(严格意义的环路死锁)!",
|
||||
})
|
||||
}else{
|
||||
this.$message({
|
||||
|
@ -563,7 +538,7 @@ export default {
|
|||
|
||||
if(cirle_deadlock){
|
||||
this.$message({
|
||||
message: "发现互斥锁死锁(严格意义的环路死锁)!",
|
||||
message: "1发现互斥锁死锁(严格意义的环路死锁)!",
|
||||
})
|
||||
}else{
|
||||
this.$message({
|
||||
|
@ -716,6 +691,7 @@ export default {
|
|||
this.javapid = this.java_pid_input;
|
||||
java_form.pwd = this.java_passwd_input;
|
||||
java_form.CmdType = cmd_type.JAVA_PID;
|
||||
java_form.deadType = this.java_dead_type;
|
||||
this.$vscode.postMessage({form: java_form});
|
||||
},
|
||||
//C本地检测输入合法性判断
|
||||
|
@ -1120,316 +1096,78 @@ export default {
|
|||
根据jstack输出信息,提取锁信息
|
||||
*/
|
||||
javalockInfoInit(data,arch){
|
||||
const common_func = function (data, lock_type) {
|
||||
let res_str = "";
|
||||
const hadHeldMutexMap = new Map(); // 锁被线程拥有 <锁, 线程ID>
|
||||
const willHeldMutexMap = new Map(); // 线程正申请的锁 <线程ID, 锁>
|
||||
data.split('\n').forEach((Info)=>{
|
||||
if(Info && Info.length){
|
||||
let count = 0;
|
||||
let tmp = Info.split('|');
|
||||
if(tmp && tmp.length >= 3){
|
||||
res_str += '线程' + tmp[0] +`申请${lock_type}`+ tmp[1] +"被线程"+ tmp[2]+"持有; ";
|
||||
hadHeldMutexMap.set(tmp[1], tmp[2]); //<锁, 线程ID>
|
||||
willHeldMutexMap.set(tmp[0], tmp[1]); //<线程ID, 锁>
|
||||
}
|
||||
}
|
||||
});
|
||||
let nodeItem = [];
|
||||
willHeldMutexMap.forEach(function(value, key) {
|
||||
hadHeldMutexMap.forEach(function (v1, k1) {
|
||||
if(v1 === key){
|
||||
nodeItem.push({
|
||||
threadID: key,
|
||||
lockID: value,
|
||||
ownID: k1
|
||||
})
|
||||
}
|
||||
})
|
||||
});
|
||||
return {
|
||||
"res_str": res_str,
|
||||
"nodeItem": nodeItem
|
||||
}
|
||||
}
|
||||
/*
|
||||
判断信号量死锁 this.java_dead_type == 1
|
||||
判断read write死锁 this.java_dead_type == 3
|
||||
*/
|
||||
if(this.java_dead_type == 1 ){
|
||||
this.local_java_data = "";
|
||||
console.log("QQQQQQQQQQ:",this.java_dead_type)
|
||||
this.semlockflag = false;
|
||||
let processIndex = 0;
|
||||
let tempsting = data;
|
||||
//以空行为分隔符
|
||||
let split1=tempsting.replace(/\t/g, " ").replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\n\n/);
|
||||
let semdataInfo=[];
|
||||
let htmlInfo=[];
|
||||
split1.forEach((item)=>{
|
||||
console.log("00000 item is:",item)
|
||||
if(item&&(item.indexOf('a java.util.concurrent.Semaphore$NonfairSync')!=-1)){
|
||||
this.semlockflag = true
|
||||
let infoObj={};
|
||||
let htmlInfoStr='';
|
||||
processIndex+=1;
|
||||
console.log("111111:",item)
|
||||
//将字符串 item 两端的空白字符删除,然后按照换行符将字符串分割成多个子串
|
||||
let splitItemArr=item.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\n/);
|
||||
console.log("222222:",splitItemArr)
|
||||
splitItemArr.forEach((item1,index)=>{
|
||||
console.log("origin info item1 is:",item1);
|
||||
let lineReg=/a java.util.concurrent.Semaphore\$NonfairSync/;
|
||||
if(index==0){
|
||||
let match = item1.match(/"([^"]+)"/);
|
||||
if(match){
|
||||
infoObj.threadName = match[1];
|
||||
}
|
||||
let threadName=item1.split('nid=')[1].split(' ')[0];
|
||||
threadName=parseInt(threadName,16)
|
||||
infoObj.threadName = threadName;
|
||||
//infoObj.threadNum = threadName;
|
||||
}
|
||||
|
||||
if(index==splitItemArr.length-1){
|
||||
let line=item1.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split('(')[1];
|
||||
line=line.replace(')','').split(':')
|
||||
infoObj.line=line[1];
|
||||
infoObj.fileName=line[0];
|
||||
}
|
||||
if(lineReg.test(item1)){
|
||||
let lock=item1.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split('<')[1];
|
||||
lock=lock.replace(')','').replace(/>/,'').split('(')
|
||||
infoObj.lockName='<'+lock[0].replace(/^\s\s*|\s\s*$/, "")+'>';
|
||||
infoObj.lockType=lock[1].replace(/^\s\s*|\s\s*$/, "");
|
||||
}
|
||||
infoObj.threadNum=Number(this.java_pid_input)+processIndex;
|
||||
});
|
||||
htmlInfoStr='线程 '+infoObj.threadName+' 等待 信号量'+infoObj.lockName;
|
||||
semdataInfo.push(infoObj);
|
||||
htmlInfo.push(htmlInfoStr);
|
||||
console.log("AAAA infoObj:",infoObj);
|
||||
console.log("BBBB htmlInfoStr",htmlInfoStr)
|
||||
}else{
|
||||
if(item&&item.indexOf("java.lang.Thread.State: WAITING")!=-1){
|
||||
/*将字符串 item 两端的空白字符删除,然后按照换行符将字符串分割成多个子串*/
|
||||
this.semlockflag = true
|
||||
let infoObj={};
|
||||
let htmlInfoStr='';
|
||||
let splitItemArr=item.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\n/);
|
||||
console.log("222222:",splitItemArr)
|
||||
splitItemArr.forEach((item1,index)=>{
|
||||
console.log("origin info item1 is:",item1)
|
||||
let lineReg=/a java.util.concurrent.Semaphore\$NonfairSync/;
|
||||
/*线程号或线程名*/
|
||||
if(index==0){
|
||||
let match = item1.match(/"([^"]+)"/);
|
||||
if(match){
|
||||
infoObj.threadName = match[1];
|
||||
}
|
||||
let threadName=item1.split('nid=')[1].split(' ')[0];
|
||||
threadName=parseInt(threadName,16)
|
||||
infoObj.threadName = threadName;
|
||||
}
|
||||
//锁或信号量
|
||||
if(item1.includes('<') && item1.includes('>')){
|
||||
const start = item1.indexOf('<') + 1; // 找到 "<" 的位置
|
||||
const end = item1.indexOf('>'); // 找到 ">" 的位置
|
||||
const objStr = item1.slice(start, end); // 截取 "<" 和 ">" 之间的字符串
|
||||
infoObj.lockName = objStr;
|
||||
}
|
||||
//文件名及行号
|
||||
if (item1.includes('$')) {
|
||||
const idx = item1.indexOf('$');
|
||||
if (idx < item1.length - 1 && /^\d$/.test(item1.charAt(idx + 1))) {
|
||||
const matched = item1.match(/\(([^)]+)\)/);
|
||||
if (matched) {
|
||||
console.log(matched[1]);
|
||||
infoObj.fileName = matched[1].split(":")[0];
|
||||
infoObj.line = matched[1].split(":")[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
htmlInfoStr='线程 '+infoObj.threadName+' 等待 信号量'+infoObj.lockName;
|
||||
semdataInfo.push(infoObj);
|
||||
htmlInfo.push(htmlInfoStr);
|
||||
console.log("AAAA infoObj:",infoObj);
|
||||
console.log("BBBB htmlInfoStr",htmlInfoStr)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
this.loading3 = false;
|
||||
if(htmlInfo.length==0){
|
||||
if(data && data.length) {
|
||||
let sem_res_str = "";
|
||||
data.split('\n').forEach((semInfo)=>{
|
||||
if(semInfo && semInfo.length){
|
||||
sem_res_str += "线程" + semInfo.replace('|', "等待信号量") + '; ';
|
||||
}
|
||||
});
|
||||
if(sem_res_str.length) this.local_java_data = sem_res_str;
|
||||
this.java_thread_info = [];
|
||||
this.echartsInit(this.java_thread_info);
|
||||
return;
|
||||
}
|
||||
this.local_java_data = "";
|
||||
this.$message({
|
||||
message: "未发现信号量死锁!",
|
||||
});
|
||||
this.java_thread_info = [];
|
||||
this.echartsInit(this.java_thread_info);
|
||||
}else{
|
||||
console.log("semdataInfo is:",semdataInfo)
|
||||
this.local_java_data += htmlInfo
|
||||
this.java_thread_info = [];
|
||||
this.echartsInit(this.java_thread_info);
|
||||
//let echartsData=this.javasemgetEchartsData(semdataInfo);
|
||||
//this.javasemechartsInit(echartsData)
|
||||
}
|
||||
}else if(this.java_dead_type == 2){
|
||||
//判断互斥锁死锁 this.java_dead_type == 2
|
||||
this.local_java_data = '';
|
||||
this.java_thread_info = [];
|
||||
if(data.includes("Found.*?deadlock")){
|
||||
let a=data.split(/Found.*?deadlock:/g)[1];
|
||||
a=a.replace(/\t+/g,'\n');
|
||||
let b=a.split(/.*?\n=+?\n+/g);
|
||||
let b1=b[1].replace('Java stack information for the threads listed above:','').replace(/^\s\s*/, "").replace(/\s\s*$/, "");
|
||||
let deadTable=this.deadTableData(b1,arch);
|
||||
console.log("AAAAA:",b1)
|
||||
|
||||
let b2=b[2].split(/Found.*?deadlock./g);
|
||||
let c1=b2[0].replace(/"/g, "");
|
||||
let d2=c1.split(/Thread-/g);
|
||||
|
||||
console.log("BBBBB:",d2)
|
||||
|
||||
if(d2&&d2.length>0){
|
||||
d2.forEach(item=>{
|
||||
if(item){
|
||||
let arrData=item.split(/:\n/g);
|
||||
let theardItem={};
|
||||
let arrData2=arrData[1].replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\n+/g);
|
||||
let val=arrData2[0].replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\(/)[1].split(/\)/)[0];
|
||||
let obj2={};
|
||||
theardItem.sourceStr=arrData2;
|
||||
//arrData2[1]等待锁,arrData2[2]拥有锁
|
||||
let index1 = arrData2[1].indexOf('<')
|
||||
let index2 = arrData2[1].indexOf('>')
|
||||
let waitlock = arrData2[1].substring(index1+1,index2)
|
||||
console.log("等待锁:",waitlock)
|
||||
index1 = arrData2[2].indexOf('<')
|
||||
index2 = arrData2[2].indexOf('>')
|
||||
let ownlock = arrData2[2].substring(index1+1,index2)
|
||||
console.log("拥有锁:",ownlock)
|
||||
console.log("code line is:",theardItem.sourceStr)
|
||||
theardItem.sourceLine=val;
|
||||
//theardItem.sourceLine线程对应代码行
|
||||
console.log("code line2 is:",theardItem.sourceLine)
|
||||
//obj2['Thread-'+arrData[0]]=theardItem;
|
||||
let lockrelation = 'Thread-'+arrData[0] +'('+ theardItem.sourceLine +')' + "等待锁" + waitlock + "拥有锁" + ownlock + ';' +'\n'
|
||||
console.log("result info is :",lockrelation)
|
||||
this.local_java_data += lockrelation
|
||||
obj2.threadID = 'Thread-'+arrData[0];
|
||||
obj2.ownID = ownlock;
|
||||
obj2.lockID = waitlock;
|
||||
this.java_thread_info.push(obj2);
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
let d1=[];
|
||||
deadTable.lockTableInfo.forEach(item => {
|
||||
let obj={};
|
||||
if(item){
|
||||
obj.lock=item.key0;
|
||||
obj.val=item.key4;
|
||||
d1.push(obj);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.javaLockInfo=deadTable.lockInfo;//死锁检测信息
|
||||
this.javaLockTableInfo=deadTable.lockTableInfo;//表格信息
|
||||
}
|
||||
//this.echartsInit(d1,obj2);
|
||||
if(this.java_thread_info.length==0){
|
||||
this.loading3=false;
|
||||
this.$message({
|
||||
message: "未发现互斥锁死锁!",
|
||||
});
|
||||
}else{
|
||||
this.echartsInit(this.java_thread_info);
|
||||
}
|
||||
}else if(this.java_dead_type == 3){
|
||||
}else if(this.java_dead_type == 2 || this.java_dead_type == 3){
|
||||
//java读写锁
|
||||
this.local_java_data = '';
|
||||
this.java_thread_info = [];
|
||||
let tempstring = data;
|
||||
//首先判断是否发生死锁
|
||||
if(tempstring.includes('Found one Java-level deadlock:')){
|
||||
//start to modify for eduction version
|
||||
const pattern = /"(Thread-\d+)":\s*waiting for ownable synchronizer\s*(0x[0-9a-f]+),\s*\(a java\.util\.concurrent\.locks\.ReentrantReadWriteLock\$NonfairSync\),\s*which is held by\s*"(Thread-\d+)"/g;
|
||||
let match;
|
||||
this.java_thread_info = [];
|
||||
let temp_arry = [];
|
||||
while ((match = pattern.exec(data)) !== null) {
|
||||
const threadWaiting = match[1];
|
||||
const address = match[2];
|
||||
const threadHolding = match[3];
|
||||
let obj4= {};
|
||||
obj4.waitthread = threadWaiting;
|
||||
obj4.lockID = address;
|
||||
obj4.holdthread = threadHolding;
|
||||
temp_arry.push(obj4);
|
||||
console.log("Thread waiting:", threadWaiting);
|
||||
console.log("Address:", address);
|
||||
console.log("Thread holding:", threadHolding);
|
||||
console.log();
|
||||
}
|
||||
//重构数组成员
|
||||
//深度拷贝
|
||||
const temp_arry_copy = JSON.parse(JSON.stringify(temp_arry));
|
||||
console.log("temp_arry is:",temp_arry)
|
||||
temp_arry.forEach((t) => {
|
||||
const holdingThread = temp_arry_copy.find((h) => h.holdthread === t.waitthread);
|
||||
if (holdingThread) {
|
||||
t.holdthread = holdingThread.lockID;
|
||||
console.log("t.holdthread(ownID):",t.holdthread)
|
||||
}
|
||||
});
|
||||
console.log("temp_array is:",temp_arry)
|
||||
console.log("temp_arry_copy is:",temp_arry_copy)
|
||||
//更改对象名称,统一对象的字段名称:threadID lockID ownID
|
||||
temp_arry.forEach((t) => {
|
||||
let obj4 = {};
|
||||
obj4.threadID = t.waitthread;
|
||||
obj4.lockID = t.lockID;
|
||||
obj4.ownID = t.holdthread;
|
||||
this.local_java_data += "线程"+ obj4.threadID + "等待读写锁"+ obj4.lockID + ",拥有读写锁"+obj4.ownID+";"
|
||||
this.java_thread_info.push(obj4);
|
||||
})
|
||||
this.echartsInit(this.java_thread_info);
|
||||
console.log("this.java_thread_info is :",this.java_thread_info);
|
||||
//end modify for eduction version
|
||||
|
||||
//以空行为分隔符,分割为数组
|
||||
|
||||
// this.java_thread_info = [];
|
||||
// let temp_arry = [];
|
||||
// let split1=tempstring.replace(/\t/g, " ").replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\n\n/);
|
||||
/* split1.forEach((item)=>{
|
||||
if((item.indexOf("Found one Java-level deadlock:")!=-1)&&(item.indexOf("=============")!=-1)){
|
||||
//将字符串 item 两端的空白字符删除,然后按照换行符将字符串分割成多个子串
|
||||
const pattern = /"(.*)":\s+waiting for ownable synchronizer (\S+), \(a java\.util\.concurrent\.locks\.ReentrantReadWriteLock\$NonfairSync\),\s+which is held by "(.*)"/g;
|
||||
let matches;
|
||||
while ((matches = pattern.exec(item)) !== null) {
|
||||
const waitingThread = matches[1];
|
||||
const objectId = matches[2];
|
||||
const holdingThread = matches[3];
|
||||
let obj3 = {};
|
||||
obj3.waitthread = waitingThread;
|
||||
obj3.lockID = objectId;
|
||||
obj3.holdthread = holdingThread;
|
||||
temp_arry.push(obj3);
|
||||
console.log(`Waiting thread: ${waitingThread}`);
|
||||
console.log(`Holding thread: ${holdingThread}`);
|
||||
console.log(`Object ID: ${objectId}`);
|
||||
}
|
||||
|
||||
//重构数组成员
|
||||
//深度拷贝
|
||||
const temp_arry_copy = JSON.parse(JSON.stringify(temp_arry));
|
||||
console.log("temp_arry is:",temp_arry)
|
||||
temp_arry.forEach((t) => {
|
||||
const holdingThread = temp_arry_copy.find((h) => h.holdthread === t.waitthread);
|
||||
if (holdingThread) {
|
||||
t.holdthread = holdingThread.lockID;
|
||||
console.log("t.holdthread(ownID):",t.holdthread)
|
||||
}
|
||||
});
|
||||
console.log("temp_array is:",temp_arry)
|
||||
console.log("temp_arry_copy is:",temp_arry_copy)
|
||||
//更改对象名称,统一对象的字段名称:threadID lockID ownID
|
||||
temp_arry.forEach((t) => {
|
||||
let obj4 = {};
|
||||
obj4.threadID = t.waitthread;
|
||||
obj4.lockID = t.lockID;
|
||||
obj4.ownID = t.holdthread;
|
||||
this.local_java_data += "线程"+ obj4.threadID + "等待读写锁"+ obj4.lockID + ",拥有读写锁"+obj4.ownID+";"
|
||||
this.java_thread_info.push(obj4);
|
||||
})
|
||||
this.echartsInit(this.java_thread_info);
|
||||
console.log("this.java_thread_info is :",this.java_thread_info);
|
||||
}
|
||||
})*/
|
||||
}else{
|
||||
//未发现死锁
|
||||
this.loading3 = false;
|
||||
this.$message({
|
||||
message: "未发现读写锁死锁!",
|
||||
});
|
||||
if(data && data.length){
|
||||
const obj = common_func(data, this.java_dead_type == 3 ? "读写锁":"互斥锁");
|
||||
this.java_thread_info = obj.nodeItem;
|
||||
if(obj.res_str.length) this.local_java_data = obj.res_str;
|
||||
this.echartsInit(this.java_thread_info);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.local_java_data = "";
|
||||
this.$message({
|
||||
message: `未发现死锁!`,
|
||||
});
|
||||
this.java_thread_info = [];
|
||||
this.echartsInit(this.java_thread_info);
|
||||
}else{
|
||||
this.$message({
|
||||
message: "请选择死锁类型!",
|
||||
|
@ -1437,64 +1175,10 @@ export default {
|
|||
}
|
||||
},
|
||||
/*
|
||||
java 互斥锁信息格式化
|
||||
*/
|
||||
deadTableData(b1,arch){
|
||||
let c='';
|
||||
if(arch&&(arch=='loong64'||arch=='loongarch64'||arch=='la64'||arch=='arm64'||arch=='sw_64'||arch=='mips64el')){//longxin5000、FT2000/4、LS3A4000
|
||||
c=b1.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\"\n\"/g);
|
||||
}else{
|
||||
c=b1.replace(/\"\n\n\"/g,'\t')
|
||||
c=c.replace(/\n\n/g,'\n');
|
||||
c=c.split(/\t/g);
|
||||
if(c.length>2){
|
||||
c.pop();
|
||||
}
|
||||
}
|
||||
let d=[];
|
||||
let d1=[];
|
||||
let processIndex=0;
|
||||
console.log("ccccccc:",c)
|
||||
c.forEach(item=>{
|
||||
processIndex+=1;
|
||||
let o=item;
|
||||
console.log("1111111:",o)
|
||||
o=o.replace(/:/, "")
|
||||
o=o.replace(/waiting to lock monitor/, "等待互斥锁").replace(/which is held by/, "被线程");
|
||||
console.log("2222222:",o)
|
||||
o='线程'+o+'占用';
|
||||
d.push(o);
|
||||
item=item.split(/:/);
|
||||
let str1=item[1].replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/waiting to lock monitor/)[1];
|
||||
str1=str1.replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/\(/);
|
||||
let str2=str1[1];
|
||||
str1=str1[0].replace(/^\s\s*/, "").replace(/\s\s*$/, "");
|
||||
str2=str2.split(/\)/);
|
||||
let str4=str2[1].split(/which is held by/)[1].replace(/"/g,"").replace(/^\s\s*/, "").replace(/\s\s*$/, "");
|
||||
let str3=str2[0].split(/,/)[1].replace(/^\s\s*/, "").replace(/\s\s*$/, "").split(/a\s+/)[1];
|
||||
str2=str2[0].split(/,/)[0].split(/\s+/)[1];
|
||||
console.log("str1 is:",str1)
|
||||
console.log("str1 is:",str2)
|
||||
console.log("str1 is:",str3)
|
||||
console.log("str1 is:",str4)
|
||||
let obj={};
|
||||
obj.key0=item[0].replace(/"/g, "");
|
||||
obj.key1=str1
|
||||
obj.key2=str2
|
||||
obj.key3=str3
|
||||
obj.key4=str4
|
||||
obj.key5=Number(this.javapid)+processIndex
|
||||
d1.push(obj);
|
||||
});
|
||||
return {
|
||||
'lockInfo':d,
|
||||
"lockTableInfo":d1
|
||||
}
|
||||
},
|
||||
/*
|
||||
c/c++死锁关系图节点数据格式化
|
||||
*/
|
||||
echartsInit(lockInfo) {
|
||||
console.log(`lockInfo -> ${JSON.stringify(lockInfo)}`);
|
||||
let data=[];
|
||||
let createdNodeArr=[];
|
||||
let threadPos={};
|
||||
|
|
Loading…
Reference in New Issue