Vm3 alpha debugger #295

Merged
rodrigorodriguez merged 29 commits from vm3-alpha-debugger into master 2022-11-29 22:05:10 +00:00
3 changed files with 43 additions and 40 deletions
Showing only changes of commit 9393081e58 - Show all commits

14
package-lock.json generated
View file

@ -43,7 +43,6 @@
"botframework-connector": "4.11.0", "botframework-connector": "4.11.0",
"botlib": "1.10.9", "botlib": "1.10.9",
"c3-chart-maker": "^0.2.8", "c3-chart-maker": "^0.2.8",
"cd": "^0.3.3",
"chrome-remote-interface": "^0.31.3", "chrome-remote-interface": "^0.31.3",
"cli-progress": "^3.11.2", "cli-progress": "^3.11.2",
"cli-spinner": "0.2.10", "cli-spinner": "0.2.10",
@ -8645,14 +8644,6 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
}, },
"node_modules/cd": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/cd/-/cd-0.3.3.tgz",
"integrity": "sha512-X2y0Ssu48ucdkrNgCdg6k3EZWjWVy/dsEywUUTeZEIW31f3bQfq65Svm+TzU1Hz+qqhdmyCdjGhUvRsSKHl/mw==",
"engines": {
"node": "*"
}
},
"node_modules/center-align": { "node_modules/center-align": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
@ -41049,11 +41040,6 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
}, },
"cd": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/cd/-/cd-0.3.3.tgz",
"integrity": "sha512-X2y0Ssu48ucdkrNgCdg6k3EZWjWVy/dsEywUUTeZEIW31f3bQfq65Svm+TzU1Hz+qqhdmyCdjGhUvRsSKHl/mw=="
},
"center-align": { "center-align": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",

View file

@ -32,21 +32,13 @@
'use strict'; 'use strict';
import { GBError, GBLog, GBMinInstance } from 'botlib'; import { GBLog, GBMinInstance } from 'botlib';
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
import { GuaribasUser } from '../../security.gbapp/models'; import { GuaribasUser } from '../../security.gbapp/models';
import { DialogKeywords } from './DialogKeywords'; import { DialogKeywords } from './DialogKeywords';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
const Swagger = require('swagger-client'); const Swagger = require('swagger-client');
const fs = require('fs'); const fs = require('fs');
import { CollectionUtil } from 'pragmatismo-io-framework'; const { spawn } = require('child_process');
import * as request from 'request-promise-native';
const urlJoin = require('url-join');
const Path = require('path');
const Fs = require('fs');
const url = require('url');
/** /**
* Web Automation services of conversation to be called by BASIC. * Web Automation services of conversation to be called by BASIC.
@ -83,6 +75,7 @@ export class DebuggerService {
debugWeb: boolean; debugWeb: boolean;
lastDebugWeb: Date; lastDebugWeb: Date;
/** /**
* SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE). * SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE).
*/ */
@ -198,16 +191,17 @@ export class DebuggerService {
GBServer.globals.debuggers[botId].state = 0; GBServer.globals.debuggers[botId].state = 0;
GBServer.globals.debuggers[botId].breaks = []; GBServer.globals.debuggers[botId].breaks = [];
GBServer.globals.debuggers[botId].stateInfo = "Stopped"; GBServer.globals.debuggers[botId].stateInfo = "Stopped";
GBServer.globals.debuggers[botId].childProcess = null;
} }
private client; private client;
public async breakpoint({ botId, botApiKey, line }) { public async breakpoint({ botId, line }) {
GBLog.info(`BASIC: Enabled breakpoint for ${botId} on ${line}.`); GBLog.info(`BASIC: Enabled breakpoint for ${botId} on ${line}.`);
GBServer.globals.debuggers[botId].breaks.push(Number.parseInt(line)); GBServer.globals.debuggers[botId].breaks.push(Number.parseInt(line));
} }
public async resume({ botId, botApiKey, force }) { public async resume({ botId }) {
if (GBServer.globals.debuggers[botId].state === 2) { if (GBServer.globals.debuggers[botId].state === 2) {
const client = GBServer.globals.debuggers[botId].client; const client = GBServer.globals.debuggers[botId].client;
await client.Debugger.resume(); await client.Debugger.resume();
@ -220,15 +214,20 @@ export class DebuggerService {
} }
} }
public async stop({ botId, botApiKey, force }) { public async stop({ botId }) {
GBServer.globals.debuggers[botId].state = 0; GBServer.globals.debuggers[botId].state = 0;
GBServer.globals.debuggers[botId].stateInfo = "Stopped"; GBServer.globals.debuggers[botId].stateInfo = "Stopped";
const client = GBServer.globals.debuggers[botId].client;
await client.Debugger.close(); const kill = ref => {
spawn('sh', ['-c', `pkill -9 -f ${ref}`]);
};
kill(GBServer.globals.debuggers[botId].childProcess);
return {status: 'OK'}; return {status: 'OK'};
} }
public async step({ botId, botApiKey }) { public async step({ botId }) {
if (GBServer.globals.debuggers[botId].state === 2) { if (GBServer.globals.debuggers[botId].state === 2) {
GBServer.globals.debuggers[botId].stateInfo = "Break"; GBServer.globals.debuggers[botId].stateInfo = "Break";
const client = GBServer.globals.debuggers[botId].client; const client = GBServer.globals.debuggers[botId].client;
@ -240,7 +239,7 @@ export class DebuggerService {
} }
} }
public async context({ botId, botApiKey, force }) { public async context({ botId }) {
const conversationId = this.conversationsMap[botId]; const conversationId = this.conversationsMap[botId];
let messages = []; let messages = [];
if (this.client) { if (this.client) {
@ -273,14 +272,24 @@ export class DebuggerService {
}; };
} }
public async debug({ botId, botApiKey, scriptName }) { public async getRunning({ botId, botApiKey, scriptName }) {
let error; let error;
botId = botId[0]; // TODO: Handle call in POST.
if (!GBServer.globals.debuggers[botId])
{
GBServer.globals.debuggers[botId]= {};
}
if (!scriptName){
scriptName = 'start';
}
if (GBServer.globals.debuggers[botId].state === 1) { if (GBServer.globals.debuggers[botId].state === 1) {
error = `Cannot DEBUG an already running process. ${botId}`; error = `Cannot DEBUG an already running process. ${botId}`;
return {error: error}; return {error: error};
} else if (GBServer.globals.debuggers[botId].state === 2) { } else if (GBServer.globals.debuggers[botId].state === 2) {
GBLog.info(`BASIC: Releasing execution ${botId} in DEBUG mode.`); GBLog.info(`BASIC: Releasing execution ${botId} in DEBUG mode.`);
await this.resume({ botId, botApiKey, force: false }); await this.resume({ botId});
return {status: 'OK'}; return {status: 'OK'};
} else { } else {
GBLog.info(`BASIC: Running ${botId} in DEBUG mode.`); GBLog.info(`BASIC: Running ${botId} in DEBUG mode.`);

View file

@ -63,6 +63,7 @@ const createVm2Pool = ({ min, max, ...limits }) => {
{ cwd: limits.cwd, shell: false } { cwd: limits.cwd, shell: false }
); );
childProcess.stdout.on('data', data => { childProcess.stdout.on('data', data => {
childProcess.socket = childProcess.socket || data.toString().trim(); childProcess.socket = childProcess.socket || data.toString().trim();
}); });
@ -75,18 +76,22 @@ const createVm2Pool = ({ min, max, ...limits }) => {
GBServer.globals.debuggers[limits.botId].state = 0; GBServer.globals.debuggers[limits.botId].state = 0;
GBServer.globals.debuggers[limits.botId].stateInfo = stderrCache; GBServer.globals.debuggers[limits.botId].stateInfo = stderrCache;
} }
if (stderrCache.includes('FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory')) { else if (stderrCache.includes('FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory')) {
limitError = 'code execution exceeed allowed memory'; limitError = 'code execution exceeed allowed memory';
kill(process); kill(process);
GBServer.globals.debuggers[limits.botId].state = 0; GBServer.globals.debuggers[limits.botId].state = 0;
GBServer.globals.debuggers[limits.botId].stateInfo = "Fail"; GBServer.globals.debuggers[limits.botId].stateInfo = 'Fail';
}
else if (stderrCache.includes('Debugger attached.')) {
GBLog.info(`BASIC: General Bots Debugger attached to Node .gbdialog process for ${limits.botId}.`);
} }
}); });
let socket = null; let socket = null;
await waitUntil(() => childProcess.socket); await waitUntil(() => childProcess.socket);
socket = net.createConnection(childProcess.socket);
socket.write(JSON.stringify({ code, scope }) + '\n'); GBServer.globals.debuggers[limits.botId].childProcess = ref;
// Only attach if called by debugger/run. // Only attach if called by debugger/run.
@ -124,7 +129,7 @@ const createVm2Pool = ({ min, max, ...limits }) => {
GBLog.info(`BASIC: Break at line ${frame.location.lineNumber + 1}`); // (zero-based) GBLog.info(`BASIC: Break at line ${frame.location.lineNumber + 1}`); // (zero-based)
GBServer.globals.debuggers[limits.botId].state = 2; GBServer.globals.debuggers[limits.botId].state = 2;
GBServer.globals.debuggers[limits.botId].stateInfo = "Break"; GBServer.globals.debuggers[limits.botId].stateInfo = 'Break';
} else { } else {
GBLog.verbose(`BASIC: Configuring breakpoints if any for ${limits.botId}...`); GBLog.verbose(`BASIC: Configuring breakpoints if any for ${limits.botId}...`);
// Waits for debugger and setup breakpoints. // Waits for debugger and setup breakpoints.
@ -150,18 +155,19 @@ const createVm2Pool = ({ min, max, ...limits }) => {
await client.Debugger.enable(); await client.Debugger.enable();
await client.Runtime.enable(); await client.Runtime.enable();
resolve(1); resolve(1);
} catch (err) { } catch (err) {
GBLog.error(err); GBLog.error(err);
kill(childProcess); kill(childProcess);
GBServer.globals.debuggers[limits.botId].state = 0; GBServer.globals.debuggers[limits.botId].state = 0;
GBServer.globals.debuggers[limits.botId].stateInfo = "Stopped"; GBServer.globals.debuggers[limits.botId].stateInfo = 'Stopped';
} }
}).on('error', err => { }).on('error', err => {
console.error(err); console.error(err);
kill(childProcess); kill(childProcess);
GBServer.globals.debuggers[limits.botId].state = 0; GBServer.globals.debuggers[limits.botId].state = 0;
GBServer.globals.debuggers[limits.botId].stateInfo = "Stopped"; GBServer.globals.debuggers[limits.botId].stateInfo = 'Stopped';
reject(err); reject(err);
}); });
}); });
@ -169,6 +175,8 @@ const createVm2Pool = ({ min, max, ...limits }) => {
await debug(); await debug();
} }
socket = net.createConnection(childProcess.socket);
socket.write(JSON.stringify({ code, scope }) + '\n');
const timer = setTimeout(() => { const timer = setTimeout(() => {
limitError = 'code execution took too long and was killed'; limitError = 'code execution took too long and was killed';