Compare commits
1
Commits
0781418aaf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
875c486416 |
@@ -250,6 +250,15 @@ honoured, so both extensions use the same SDK.
|
||||
terminal and the *Problems* panel (`$msCompile`).
|
||||
- The *.NET Solution* output channel logs every `dotnet` invocation.
|
||||
|
||||
## Platforms
|
||||
|
||||
Windows, Linux and macOS. The only platform-specific code is around processes: the
|
||||
apphost is `MyGame.Editor.exe` on Windows and `MyGame.Editor` elsewhere; the process
|
||||
list comes from `wmic` (or PowerShell's CIM query where wmic is gone) on Windows and
|
||||
`ps -eo pid,ppid,args` elsewhere; and stopping hot reload uses `taskkill /T` on Windows
|
||||
and a process-group signal on Unix, where `dotnet watch` is started detached for that
|
||||
reason.
|
||||
|
||||
## Development
|
||||
|
||||
```
|
||||
|
||||
@@ -16,7 +16,9 @@ export interface ProcessInfo {
|
||||
export async function listProcesses(): Promise<ProcessInfo[]> {
|
||||
if (process.platform !== 'win32') {
|
||||
try {
|
||||
return parsePs(await capture('ps', ['-eo', 'pid=,ppid=,comm=']));
|
||||
// args rather than comm: comm is the kernel's 15-character name, which would
|
||||
// cut "MyGame.Editor.Tools" short and never match the assembly name.
|
||||
return parsePs(await capture('ps', ['-eo', 'pid=,ppid=,args=']));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
@@ -67,12 +69,18 @@ export function parseWmicCsv(text: string): ProcessInfo[] {
|
||||
return processes;
|
||||
}
|
||||
|
||||
/** Parses `ps -eo pid=,ppid=,args=`: the name is the basename of the command, without its arguments. */
|
||||
export function parsePs(text: string): ProcessInfo[] {
|
||||
const processes: ProcessInfo[] = [];
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
const match = /^\s*(\d+)\s+(\d+)\s+(.*\S)\s*$/.exec(line);
|
||||
const match = /^\s*(\d+)\s+(\d+)\s+(\S+)/.exec(line);
|
||||
if (match) {
|
||||
processes.push({ pid: Number(match[1]), parentPid: Number(match[2]), name: match[3] });
|
||||
const command = match[3].replace(/^\[|\]$/g, ''); // kernel threads show as [name]
|
||||
processes.push({
|
||||
pid: Number(match[1]),
|
||||
parentPid: Number(match[2]),
|
||||
name: command.slice(command.lastIndexOf('/') + 1),
|
||||
});
|
||||
}
|
||||
}
|
||||
return processes;
|
||||
|
||||
@@ -111,6 +111,10 @@ export class HotReloadSession implements vscode.Disposable {
|
||||
cwd: spec.cwd,
|
||||
env,
|
||||
windowsHide: true,
|
||||
// On Unix a detached child leads its own process group, which is what lets
|
||||
// stop() kill the watcher *and* the application below it with one signal.
|
||||
// Windows has taskkill /T for that and does not need it.
|
||||
detached: process.platform !== 'win32',
|
||||
});
|
||||
|
||||
this.child.stdout?.on('data', chunk => this.consume(String(chunk)));
|
||||
|
||||
@@ -44,6 +44,9 @@ suite('process lookup', () => {
|
||||
const csv = '\r\nNode,Name,ParentProcessId,ProcessId\r\nPC,dotnet.exe,1,100\r\nPC,MyGame.Editor.exe,100,103\r\n';
|
||||
assert.deepStrictEqual(parseWmicCsv(csv), [
|
||||
{ pid: 100, parentPid: 1, name: 'dotnet.exe' }, { pid: 103, parentPid: 100, name: 'MyGame.Editor.exe' }]);
|
||||
assert.deepStrictEqual(parsePs(' 100 1 /usr/bin/dotnet watch run\n 103 100 /home/u/MyGame/Bin/MyGame.Editor --flag\n 2 0 [kthreadd]\n'), [
|
||||
{ pid: 100, parentPid: 1, name: 'dotnet' }, { pid: 103, parentPid: 100, name: 'MyGame.Editor' },
|
||||
{ pid: 2, parentPid: 0, name: 'kthreadd' }]);
|
||||
assert.deepStrictEqual(parsePs(' 100 1 dotnet\n 103 100 MyGame.Editor\n'), [
|
||||
{ pid: 100, parentPid: 1, name: 'dotnet' }, { pid: 103, parentPid: 100, name: 'MyGame.Editor' }]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user