1
- import { ChildProcessWithoutNullStreams } from "child_process" ;
1
+ import * as util from "util" ;
2
+ import * as child_process from "child_process" ;
2
3
import { Process , ProcessTree } from "." ;
3
- import { Transform } from "stream" ;
4
+
5
+ const exec = util . promisify ( child_process . execFile ) ;
4
6
5
7
/** Parses process information from a given line of process output. */
6
8
export type ProcessTreeParser = ( line : string ) => Process | undefined ;
@@ -10,93 +12,30 @@ export type ProcessTreeParser = (line: string) => Process | undefined;
10
12
*/
11
13
export abstract class BaseProcessTree implements ProcessTree {
12
14
/**
13
- * Spawn the process responsible for collecting all processes on the system.
15
+ * Get the command responsible for collecting all processes on the system.
14
16
*/
15
- protected abstract spawnProcess ( ) : ChildProcessWithoutNullStreams ;
17
+ protected abstract getCommand ( ) : string ;
18
+
19
+ /**
20
+ * Get the list of arguments used to launch the command.
21
+ */
22
+ protected abstract getCommandArguments ( ) : string [ ] ;
16
23
17
24
/**
18
25
* Create a new parser that can read the process information from stdout of the process
19
26
* spawned by {@link spawnProcess spawnProcess()}.
20
27
*/
21
28
protected abstract createParser ( ) : ProcessTreeParser ;
22
29
23
- listAllProcesses ( ) : Promise < Process [ ] > {
24
- return new Promise < Process [ ] > ( ( resolve , reject ) => {
25
- const proc = this . spawnProcess ( ) ;
26
- const parser = this . createParser ( ) ;
27
-
28
- // Capture processes from stdout
29
- const processes : Process [ ] = [ ] ;
30
- proc . stdout . pipe ( new LineBasedStream ( ) ) . on ( "data" , ( line ) => {
31
- const process = parser ( line . toString ( ) ) ;
32
- if ( process && process . id !== proc . pid ) {
33
- processes . push ( process ) ;
34
- }
35
- } ) ;
36
-
37
- // Resolve or reject the promise based on exit code/signal/error
38
- proc . on ( "error" , reject ) ;
39
- proc . on ( "exit" , ( code , signal ) => {
40
- if ( code === 0 ) {
41
- resolve ( processes ) ;
42
- } else if ( signal ) {
43
- reject (
44
- new Error (
45
- `Unable to list processes: process exited due to signal ${ signal } ` ,
46
- ) ,
47
- ) ;
48
- } else {
49
- reject (
50
- new Error (
51
- `Unable to list processes: process exited with code ${ code } ` ,
52
- ) ,
53
- ) ;
54
- }
55
- } ) ;
56
- } ) ;
57
- }
58
- }
59
-
60
- /**
61
- * A stream that emits each line as a single chunk of data. The end of a line is denoted
62
- * by the newline character '\n'.
63
- */
64
- export class LineBasedStream extends Transform {
65
- private readonly newline : number = "\n" . charCodeAt ( 0 ) ;
66
- private buffer : Buffer = Buffer . alloc ( 0 ) ;
67
-
68
- override _transform (
69
- chunk : Buffer ,
70
- _encoding : string ,
71
- callback : ( ) => void ,
72
- ) : void {
73
- let currentIndex = 0 ;
74
- while ( currentIndex < chunk . length ) {
75
- const newlineIndex = chunk . indexOf ( this . newline , currentIndex ) ;
76
- if ( newlineIndex === - 1 ) {
77
- this . buffer = Buffer . concat ( [
78
- this . buffer ,
79
- chunk . subarray ( currentIndex ) ,
80
- ] ) ;
81
- break ;
30
+ async listAllProcesses ( ) : Promise < Process [ ] > {
31
+ const execCommand = exec ( this . getCommand ( ) , this . getCommandArguments ( ) ) ;
32
+ const parser = this . createParser ( ) ;
33
+ return ( await execCommand ) . stdout . split ( "\n" ) . flatMap ( ( line ) => {
34
+ const process = parser ( line . toString ( ) ) ;
35
+ if ( ! process || process . id === execCommand . child . pid ) {
36
+ return [ ] ;
82
37
}
83
-
84
- const newlineChunk = chunk . subarray ( currentIndex , newlineIndex ) ;
85
- const line = Buffer . concat ( [ this . buffer , newlineChunk ] ) ;
86
- this . push ( line ) ;
87
- this . buffer = Buffer . alloc ( 0 ) ;
88
-
89
- currentIndex = newlineIndex + 1 ;
90
- }
91
-
92
- callback ( ) ;
93
- }
94
-
95
- override _flush ( callback : ( ) => void ) : void {
96
- if ( this . buffer . length ) {
97
- this . push ( this . buffer ) ;
98
- }
99
-
100
- callback ( ) ;
38
+ return [ process ] ;
39
+ } ) ;
101
40
}
102
41
}
0 commit comments