修改一些bug

This commit is contained in:
machunyu 2022-10-13 19:03:13 +08:00
parent b253ff688f
commit c679cb81ee
5 changed files with 87 additions and 146 deletions

View File

@ -16,6 +16,11 @@ deadlock-detect 是一款基于OpenKylin社区kylin-code的拓展插件用于
- 远程环境进程死锁检测
## 使用方法
#### 检查依赖
依赖binutils、libc-bin、sshpass软件包
安装方式```sudo apt install binutils libc-bin sshpass -y```
内核版本在4.19以上支持BPF内核选项```CONFIG_BPF_EVENTS=y```
#### C/C++ 多线程序锁分析
* 打开目标C/C++工程,点击`终端`->`配置任务` 选择`deadlockdetect: 可执行程序锁检测`
task.json文件中自动添加的锁检测任务如下

View File

@ -206,8 +206,10 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
this.checkedPid = parseInt(result[3].trim());
execDetect(this.passwd, result[1].trim(), this.checkedPid, (detectResult)=>{
if(detectResult.match(/fatal/)?.length){
vscode.window.showWarningMessage("被检测程序存在严重问题!")
kill(this.checkedPid, 9);
vscode.window.showWarningMessage("被检测程序存在严重问题!");
}else if(detectResult.match(/deadlock/)?.length){
kill(this.checkedPid, 9);
vscode.window.showWarningMessage("被检测程序存在死锁!");
}
if(detectResult.match(/normal|fatal|deadlock/)?.length){
@ -219,7 +221,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal {
enableScripts: true,
retainContextWhenHidden: true,
}
)
);
webPanel.webview.html = prase_yaml2html(this.command, this.context.extensionPath, webPanel.webview, detectResult);
}else{
vscode.window.showInformationMessage("程序已退出,但未检测到相关锁信息");

View File

@ -5,7 +5,8 @@ import path = require('path');
import fs = require("fs");
import {DetectTaskProvider} from './detectTaskProvider';
import { homedir } from 'os';
import {exec} from 'child_process';
import {testPwd} from './utils';
// linux命令操作模块
var child = require('child_process');
const { pid } = require('process');
@ -26,23 +27,6 @@ function getWebViewContent(context: vscode.ExtensionContext, templatePath: strin
return html;
}
function is_pid_exist(pid: string) {
return new Promise(function(resolve, reject) {
child.exec(`ps -ef`, (e: any, x: string, c: any) => {
if(e){
reject('ps命令执行错误!')
}else{
let search=new RegExp("\\s+"+pid+"\\s+");
let exist=search.test(x);
if(exist){
resolve('1');
}else{
resolve('-1');
}
}
})
});
}
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
@ -50,39 +34,18 @@ export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "deadlock-detect" is now active!');
let newFn={
local_detect_deadlock:function (message: any ,panel: vscode.WebviewPanel){
let form=message.form;
if(form.CmdType==1){
child.exec(`echo '${form.pwd}' | sudo -S ps`, (e: any, x: string, c: any) => {
if(e){
form.success='error-pwd';
form.msg='您输入的密码错误!';
if(e.message.indexOf('sudoers')!=-1){
form.msg='当前用户无sudo权限请在拥有sudo权限后重试!';
}
panel.webview.postMessage({
res: form
})
if(form.CmdType===1){
testPwd(form.pwd, (ok)=>{
if(!ok){
vscode.window.showErrorMessage("用户密码不匹配");
return;
}
})
let pid_exist = is_pid_exist(form.pid);
pid_exist.then((result)=>{
console.log(result);
if(result=='-1'){
form.success='error-pid';
form.msg='进程号不存在,请重新输入';
panel.webview.postMessage({
res: form
})
return
}else if(result=='1'){
child.exec(`echo '${form.pwd}' | sudo -S ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`, (e: any, x: string, c: any) => {
if(fs.existsSync(`/proc/${form.pid}`))
{
exec(`echo '${form.pwd}' | sudo -S ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`, (e: any, x: string, c: string) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(!e){
form.data =x;
@ -96,106 +59,60 @@ export function activate(context: vscode.ExtensionContext) {
res: form});
}
});
}else{
vscode.window.showErrorMessage(`当前不存在${form.pid}进程`);
}
})
});
}
},
remote_detect_deadlock:function (message: any ,panel: vscode.WebviewPanel){
let form=message.form;
if(form.CmdType==3){
if(form.CmdType===3){
// sudo apt install sshpass
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip}`, (e: any, x: string, c: any) => {
exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ls /proc/${form.pid}'`, (e: any, x: string, c: string) => {
if(e){
form.success='error-ssh-login';
form.msg='无法登录您指定的远端系统请确保具有ssh登录权限!';
panel.webview.postMessage({
res: form
})
return;
}
})
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ps'`, (e: any, x: string, c: any) => {
if(e){
form.success='error-not-sudoer';
form.msg='user is not sudoer!';
if(e.message.indexOf('sudoers')!=-1){
form.msg='当前用户无sudo权限请在拥有sudo权限后重试!';
}
panel.webview.postMessage({
res: form
})
return;
}
})
let pid_exist = new Promise(function(resolve, reject) {
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ps -ef'`, (e: any, x: string, c: any) => {
if(e){
reject('ps命令执行错误!')
if(c.includes('Permission denied')){
vscode.window.showErrorMessage("远程主机用户名或密码错误");
}else if(c.includes('ls:')){
vscode.window.showErrorMessage(`远程主机不存在${form.pid}进程`);
}else{
let search=new RegExp("\\s+"+form.pid+"\\s+");
let exist=search.test(x);
if(exist){
resolve('1');
}else{
resolve('-1');
}
vscode.window.showErrorMessage(`远程主机无法路由,或其他未知错误`);
}
})
});
pid_exist.then((result)=>{
console.log(result);
if(result=='-1'){
form.success='error-pid';
form.msg='进程号不存在,请重新输入';
panel.webview.postMessage({
res: form
})
return;
}else if(result=='1'){
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} '[ ! -d .deadlock-detect ] && mkdir .deadlock-detect || ls .deadlock-detect'`, (e: any, x: string, c: any) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(e){
form.success='error-mkdir';
form.msg='创建目录.deadlock-detect失败!';
panel.webview.postMessage({
res: form});
return;
}
});
}
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} '[ ! -d .deadlock-detect ] && mkdir .deadlock-detect || ls .deadlock-detect'`, (e: any, x: string, c: any) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(e){
vscode.window.showErrorMessage("远程主机无法创建目录, 请确认登录用户是否拥有权限.");
return;
}
child.exec(`sshpass -p '${form.pwd}' scp -o StrictHostKeyChecking=no ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.user}@${form.ip}:./.deadlock-detect`, (e: any, x: string, c: any) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(e){
form.success='error-scp';
form.msg='scp EXE failed!';
panel.webview.postMessage({
res: form});
vscode.window.showErrorMessage("远程主机无法拷贝文件, 请确认登录用户是否拥有权限.");
return;
}
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ./.deadlock-detect/detect_deadlock ${form.pid}'`, (e: any, x: string, c: any) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(!e){
form.data =x;
form.success='success';
panel.webview.postMessage({
res: form});
}
else{
form.success='error';
panel.webview.postMessage({
res: form});
}
});
});
child.exec(`sshpass -p '${form.pwd}' ssh -o StrictHostKeyChecking=no ${form.user}@${form.ip} 'echo "${form.pwd}" | sudo -S ./.deadlock-detect/detect_deadlock ${form.pid}'`, (e: any, x: string, c: any) => {
// console.log(`echo '${form.pwd}' | sudo ${__dirname}/../detect-tools/x86_64/detect_deadlock ${form.pid}`);
if(!e){
form.data =x;
console.log(x);
form.success='success';
panel.webview.postMessage({
res: form});
}
else{
form.success='error';
panel.webview.postMessage({
res: form});
}
});
}
})
});
});
}
},
}
}
};
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
@ -224,9 +141,26 @@ export function activate(context: vscode.ExtensionContext) {
});
panel.webview.html = getWebViewContent(context, 'dist/index.html');
});
const workspaceRoot = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) ? vscode.workspace.workspaceFolders[0].uri.fsPath : homedir();
detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context));
exec(`which sshpass`, (e, o, err)=>{
if(e){
vscode.window.showWarningMessage('当前环境缺失sshpass工具,C/C++程序远程死锁检测功能受限,请执行 sudo apt install sshpass 安装.');
return;
}
});
exec(`uname -r`, (e, o, err)=>{
if(e){
vscode.window.showWarningMessage("检测环境失败, C/C++程序锁分析插件功能受限");
return;
}
exec(`grep -r "^CONFIG_BPF_EVENTS=" /boot/config-${o}`, (e1, o1, err1)=>{
if(e1){
vscode.window.showWarningMessage("由于内核限制, C/C++程序锁分析插件功能受限");
return;
}
const workspaceRoot = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) ? vscode.workspace.workspaceFolders[0].uri.fsPath : homedir();
detectTaskProvider = vscode.tasks.registerTaskProvider(DetectTaskProvider.customBuildScriptType, new DetectTaskProvider(workspaceRoot, context));
});
});
context.subscriptions.push(disposable);
}

View File

@ -45,7 +45,7 @@ function circledNodesPosition(x:number, y: number, index: number, nodesLen: numb
return {
x: Math.sin((ahd * index)) * 15 + x,
y: Math.cos((ahd * index)) * 15 + y
}
};
}
// warn: "process exit"
@ -119,7 +119,7 @@ function product_deadlockinfo_to_html(cmd: string, echartsPath: string, deadlock
type: 'graph',
layout: 'none',
roam: true,
symbolSize: 80,
symbolSize: 70,
label: {
show: true
},
@ -129,7 +129,7 @@ function product_deadlockinfo_to_html(cmd: string, echartsPath: string, deadlock
normal: {
show: true,
textStyle: {
fontSize: 8
fontSize: 14
},
formatter: "{c}"
}
@ -139,7 +139,7 @@ function product_deadlockinfo_to_html(cmd: string, echartsPath: string, deadlock
lineStyle: {
opacity: 0.9,
width: 2,
curveness: -0.1
curveness: 0
}
}
]
@ -151,7 +151,7 @@ function product_deadlockinfo_to_html(cmd: string, echartsPath: string, deadlock
</script>
</body>
</html>
`
`;
}
// 输入正常锁信息的html
@ -211,7 +211,7 @@ function product_normalinfo_to_html(cmd: string, echartsPath: string, mutexInfo:
</script>
</body>
</html>
`
`;
}
// 线程退出但是未释放锁
@ -241,7 +241,7 @@ function product_fatalinfo_to_html(cmd: string, fatalInfo:string) {
</div>
</body>
</html>
`
`;
}
// 发生死锁
@ -306,27 +306,27 @@ function parse_mutexInfo(mutexObj:MutexInfo[], sinfoList:SourceInfo[], dimension
<li>
(${key}) ${info[0]} , ${info[1]} , ${info[2]} .
</li>
`
`;
}else{
miStr += `
<li>
(${key}) ${info[0]} , ${info[1]} .
</li>
`
`;
}
}
}
miStr += `
</ul>
</li>
`
`;
sinfoList.push(sinfo);
});
dimensionsList.push('product');
mutexSet.forEach((mutex)=>{
dimensionsList.push(mutex);
});
for (let index = 0; index < sinfoList.length; index++) {
for (let index = 0; index < dimensionsList.length-1; index++) {
seriesList.push({type:'bar'});
}
return miStr;
@ -387,7 +387,7 @@ function parse_deadlockInfo(dlInfo:DeadlockInfo, dataList: object[], linksList:
target: (index+1)%dlInfo.cycle.length,
value: `线程 ${value}`,
lineStyle: {
curveness: 0.2
curveness: -0.2
}
});
}

View File

@ -15,7 +15,7 @@
<el-button type="primary" v-on:click="begin_local_check()">开始检测</el-button>
</div>
<br />
<el-card v-loading="loading" element-loading-text="正在检测..." class="box-card" style="width: 80%;margin: auto;">
<el-card class="box-card" style="width: 80%;margin: auto;">
<div slot="header" class="clearfix" v-if="loading == false">
<span>{{ local_thread_data }}</span>
</div>