Skip to content

Commit

Permalink
Merge pull request #1 from A-Kovalev-Playrix/dev/breakpoins-pulling
Browse files Browse the repository at this point in the history
PF from tomblind: Pull support for breakpoints update
  • Loading branch information
Ismoh authored Oct 12, 2023
2 parents d51ee29 + b6b2b13 commit 54262e5
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 16 deletions.
42 changes: 41 additions & 1 deletion debugger/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@ export namespace Debugger {
inputFile = io.stdin;
}

const pullFileEnv: LuaDebug.PullFileEnv = "LOCAL_LUA_DEBUGGER_PULL_FILE";
const pullFilePath = os.getenv(pullFileEnv);
let lastPullSeek = 0;
let pullFile: LuaFile | null;
if (pullFilePath && pullFilePath.length > 0) {
const [file, err] = io.open(pullFilePath, "r+");
if (!file) {
luaError(`Failed to open pull file "${pullFilePath}": ${err}\n`);
}
pullFile = file as LuaFile;
pullFile.setvbuf("no");
const [fileSize, errorSeek] = pullFile.seek("end");
if (!fileSize) {
luaError(`Failed to read pull file "${pullFilePath}": ${errorSeek}\n`);
} else {
lastPullSeek = fileSize;
}
} else {
pullFile = null;
}

let skipNextBreak = false;

const enum HookType {
Expand Down Expand Up @@ -475,6 +496,7 @@ export namespace Debugger {
let breakAtDepth = -1;
let breakInThread: Thread | undefined;
let updateHook: { (): void };
let isDebugHookDisabled = true;
let ignorePatterns: string[] | undefined;
let inDebugBreak = false;

Expand Down Expand Up @@ -848,6 +870,10 @@ export namespace Debugger {
const skipUnmappedLines = (os.getenv(stepUnmappedLinesEnv) !== "1");

function debugHook(event: "call" | "return" | "tail return" | "count" | "line", line?: number) {
if (isDebugHookDisabled) {
return;
}

//Stepping
if (breakAtDepth >= 0) {
const activeThread = getActiveThread();
Expand Down Expand Up @@ -1143,7 +1169,10 @@ export namespace Debugger {
}

updateHook = function() {
if (breakAtDepth < 0 && Breakpoint.getCount() === 0) {
isDebugHookDisabled = breakAtDepth < 0 && Breakpoint.getCount() === 0;
// Do not disable debugging in luajit environment with pull breakpoints support enabled
// or functions will be jitted and will lose debug info of lines and files
if (isDebugHookDisabled && (_G["jit"] === null || pullFile === null)) {
debug.sethook();

for (const [thread] of pairs(threadIds)) {
Expand Down Expand Up @@ -1173,6 +1202,7 @@ export namespace Debugger {
coroutine.wrap = luaCoroutineWrap;
coroutine.resume = luaCoroutineResume;

isDebugHookDisabled = true;
debug.sethook();

for (const [thread] of pairs(threadIds)) {
Expand Down Expand Up @@ -1251,4 +1281,14 @@ export namespace Debugger {
return luaError(message, 2);
}
}

export function pullBreakpoints(): void {
if (pullFile) {
const newPullSeek = pullFile.seek("end")[0] as number;
if (newPullSeek > lastPullSeek) {
lastPullSeek = newPullSeek;
triggerBreak();
}
}
}
}
5 changes: 5 additions & 0 deletions debugger/lldebugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export function stop(): void {
Debugger.clearHook();
}

//Pull breakpoints change
export function pullBreakpoints(): void {
Debugger.pullBreakpoints();
}

//Load and debug the specified file
export function runFile(filePath: unknown, breakImmediately?: boolean, arg?: unknown[]): LuaMultiReturn<unknown[]> {
if (typeof filePath !== "string") {
Expand Down
1 change: 1 addition & 0 deletions debugger/protocol.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,5 @@ declare namespace LuaDebug {
type StepUnmappedLinesEnv = "LOCAL_LUA_DEBUGGER_STEP_UNMAPPED_LINES";
type InputFileEnv = "LOCAL_LUA_DEBUGGER_INPUT_FILE";
type OutputFileEnv = "LOCAL_LUA_DEBUGGER_OUTPUT_FILE";
type PullFileEnv = "LOCAL_LUA_DEBUGGER_PULL_FILE";
}
77 changes: 75 additions & 2 deletions extension/debugPipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,34 @@ import * as crypto from "crypto";
import * as net from "net";
import * as childProcess from "child_process";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";

export interface DebugPipe {
open: (onData: (data: unknown) => void, onError: (err: unknown) => void) => void;
close: () => void;
write: (data: string) => void;
openPull: (onError: (err: unknown) => void) => void;
requestPull: () => void;
getOutputPipePath: () => string;
getInputPipePath: () => string;
getPullPipePath: () => string;
}

export function createNamedPipe(): DebugPipe {
const pipeId = crypto.randomBytes(16).toString("hex");
const outputPipePath = `\\\\.\\pipe\\lldbg_out_${pipeId}`;
const inputPipePath = `\\\\.\\pipe\\lldbg_in_${pipeId}`;
const pullPipePath = `\\\\.\\pipe\\lldbg_pull_${pipeId}`;
let outputPipe: net.Server | null = null;
let inputPipe: net.Server | null = null;
let pullPipe: net.Server | null = null;
let inputStream: net.Socket | null;
let pullStream: net.Socket | null;
let onErrorCallback: ((err: unknown) => void) | null = null;
return {
open: (onData, onError) => {
onErrorCallback = onError;
outputPipe = net.createServer(
stream => {
stream.on("data", onData);
Expand All @@ -35,31 +45,56 @@ export function createNamedPipe(): DebugPipe {
);
inputPipe.listen(inputPipePath);
},
openPull: (onError: (err: unknown) => void) => {
if (!onErrorCallback) {
onErrorCallback = onError;
}

pullPipe = net.createServer(
stream => {
stream.on("error", err => {
onError(`error on pull pipe: ${err}`);
});
pullStream = stream;
}
);
pullPipe.listen(pullPipePath);
},

close: () => {
outputPipe?.close();
outputPipe = null;
inputPipe?.close();
inputPipe = null;
inputStream = null;
pullPipe = null;
pullStream = null;
},

write: data => {
inputStream?.write(data);
},
requestPull: () => {
pullStream?.write("pull|\n");
},

getOutputPipePath: () => outputPipePath,
getInputPipePath: () => inputPipePath,
getPullPipePath: () => pullPipePath,
};
}

export function createFifoPipe(): DebugPipe {
const pipeId = crypto.randomBytes(16).toString("hex");
const outputPipePath = `/tmp/lldbg_out_${pipeId}`;
const inputPipePath = `/tmp/lldbg_in_${pipeId}`;
let outputFd: number | null;
let inputFd: number | null;
let pullPipePath = "";
let debuggerTmpDir = "";
let outputFd: number | null = null;
let inputFd: number | null = null;
let pullFd: number | null = null;
let inputStream: fs.WriteStream | null = null;
let pullStream: fs.WriteStream | null = null;
let onErrorCallback: ((err: unknown) => void) | null = null;
return {
open: (onData, onError) => {
Expand Down Expand Up @@ -113,7 +148,27 @@ export function createFifoPipe(): DebugPipe {
);
}
);
},

openPull: (onError: (err: unknown) => void) => {
if (!onErrorCallback) {
onErrorCallback = onError;
}

const appPrefix = "lldebugger";
try {
debuggerTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix));
pullPipePath = path.join(debuggerTmpDir, "pull.txt");

const fd = fs.openSync(
pullPipePath,
fs.constants.O_WRONLY | fs.constants.O_CREAT
);
pullFd = fd;
pullStream = fs.createWriteStream(null as unknown as fs.PathLike, {fd});
} catch (e: unknown) {
onErrorCallback(e);
}
},

close: () => {
Expand Down Expand Up @@ -141,13 +196,31 @@ export function createFifoPipe(): DebugPipe {
}
);
}
inputStream = null;
try {
if (pullFd !== null) {
fs.close(pullFd);
fs.rmSync(pullPipePath);
pullFd = null;
}
pullStream = null;
if (debuggerTmpDir.length > 0) {
fs.rmdirSync(debuggerTmpDir);
}
} catch (e: unknown) {
onErrorCallback?.(e);
}
},

write: data => {
inputStream?.write(data);
},
requestPull: () => {
pullStream?.write("pull|\n");
},

getOutputPipePath: () => outputPipePath,
getInputPipePath: () => inputPipePath,
getPullPipePath: () => pullPipePath,
};
}
1 change: 1 addition & 0 deletions extension/launchConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface LaunchConfig {
verbose?: boolean;
stopOnEntry?: boolean;
breakInCoroutines?: boolean;
pullBreakpointsSupport?: boolean;
stepUnmappedLines?: boolean;
scriptFiles?: string[];
ignorePatterns?: string[];
Expand Down
Loading

0 comments on commit 54262e5

Please sign in to comment.