@@ -6,7 +6,14 @@ import { EOL as SystemEOL } from 'node:os'
6
6
7
7
const EOL = / ( \r \n ) | ( \n \r ) | \n | \r /
8
8
const IS_WIN = process . platform === 'win32'
9
- const isBin = ( f :string ) : boolean => fs . existsSync ( f ) && fs . lstatSync ( f ) . isFile ( )
9
+ const isBin = ( f : string ) : boolean => {
10
+ if ( f === '' ) return false
11
+ if ( ! f . includes ( '/' ) ) return true
12
+ if ( ! fs . existsSync ( f ) ) return false
13
+
14
+ const stat = fs . lstatSync ( f )
15
+ return stat . isFile ( ) || stat . isSymbolicLink ( )
16
+ }
10
17
11
18
export type TPsLookupCallback = ( err : any , processList ?: TPsLookupEntry [ ] ) => void
12
19
@@ -39,38 +46,44 @@ export type TPsNext = (err?: any) => void
39
46
* @param {String } query.command RegExp String
40
47
* @param {String } query.arguments RegExp String
41
48
* @param {String|String[] } query.psargs
42
- * @param {Function } callback
43
- * @param {Object=null } callback .err
44
- * @param {Object[] } callback .processList
49
+ * @param {Function } cb
50
+ * @param {Object=null } cb .err
51
+ * @param {Object[] } cb .processList
45
52
* @return {Object }
46
53
*/
47
- export const lookup = ( query : TPsLookupQuery , callback : TPsLookupCallback ) => {
48
- // add 'lx' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments
49
- const { psargs = [ '-lx' ] } = query
54
+ export const lookup = ( query : TPsLookupQuery = { } , cb : TPsLookupCallback = noop ) => {
55
+ const { promise , resolve , reject } = makeDeferred ( )
56
+ const { psargs = [ '-lx' ] } = query // add 'lx' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments
50
57
const args = typeof psargs === 'string' ? psargs . split ( / \s + / ) : psargs
58
+ const extract = IS_WIN ? extractWmic : identity
59
+ const callback : TSpawnCtx [ 'callback' ] = ( err , { stdout} ) => {
60
+ if ( err ) {
61
+ reject ( err )
62
+ cb ( err )
63
+ return
64
+ }
65
+
66
+ const list = parseProcessList ( extract ( stdout ) , query )
67
+ resolve ( list )
68
+ cb ( null , list )
69
+ }
51
70
const ctx : TSpawnCtx = IS_WIN
52
71
? {
53
72
cmd : 'cmd' ,
54
73
input : 'wmic process get ProcessId,ParentProcessId,CommandLine \n' ,
55
- callback ( err , { stdout} ) {
56
- if ( err ) return callback ( err )
57
-
58
- callback ( null , parseProcessList ( extractWmic ( stdout ) , query ) )
59
- } ,
74
+ callback,
60
75
run ( cb ) { cb ( ) }
61
76
}
62
77
: {
63
78
cmd : 'ps' ,
64
79
args,
65
80
run ( cb ) { cb ( ) } ,
66
- callback ( err , { stdout} ) {
67
- if ( err ) return callback ( err )
68
-
69
- return callback ( null , parseProcessList ( stdout , query ) )
70
- }
81
+ callback,
71
82
}
72
83
73
84
exec ( ctx )
85
+
86
+ return promise
74
87
}
75
88
76
89
export const parseProcessList = ( output : string , query : TPsLookupQuery = { } ) => {
@@ -112,15 +125,15 @@ export const extractWmic = (stdout: string): string => {
112
125
* @param next
113
126
*/
114
127
// eslint-disable-next-line sonarjs/cognitive-complexity
115
- export const kill = ( pid : string | number , opts ?: TPsNext | TPsKillOptions | TPsKillOptions [ 'signal' ] , next ?: TPsNext ) => {
128
+ export const kill = ( pid : string | number , opts ?: TPsNext | TPsKillOptions | TPsKillOptions [ 'signal' ] , next ?: TPsNext ) : Promise < void > => {
116
129
if ( typeof opts == 'function' ) {
117
- kill ( pid , undefined , opts )
118
- return
130
+ return kill ( pid , undefined , opts )
119
131
}
120
132
if ( typeof opts == 'string' || typeof opts == 'number' ) {
121
- kill ( pid , { signal : opts } , next )
122
- return
133
+ return kill ( pid , { signal : opts } , next )
123
134
}
135
+
136
+ const { promise, resolve, reject } = makeDeferred ( )
124
137
const {
125
138
timeout = 30 ,
126
139
signal = 'SIGTERM'
@@ -129,7 +142,10 @@ export const kill = (pid: string | number, opts?: TPsNext | TPsKillOptions | TPs
129
142
try {
130
143
process . kill ( + pid , signal )
131
144
} catch ( e ) {
132
- return next ?.( e )
145
+ reject ( e )
146
+ next ?.( e )
147
+
148
+ return promise
133
149
}
134
150
135
151
let checkConfident = 0
@@ -142,6 +158,7 @@ export const kill = (pid: string | number, opts?: TPsNext | TPsKillOptions | TPs
142
158
143
159
if ( err ) {
144
160
clearTimeout ( checkTimeoutTimer )
161
+ reject ( err )
145
162
finishCallback ?.( err )
146
163
}
147
164
@@ -154,6 +171,7 @@ export const kill = (pid: string | number, opts?: TPsNext | TPsKillOptions | TPs
154
171
checkConfident ++
155
172
if ( checkConfident === 5 ) {
156
173
clearTimeout ( checkTimeoutTimer )
174
+ resolve ( )
157
175
finishCallback ?.( )
158
176
} else {
159
177
checkKilled ( finishCallback )
@@ -167,7 +185,11 @@ export const kill = (pid: string | number, opts?: TPsNext | TPsKillOptions | TPs
167
185
checkIsTimeout = true
168
186
next ( new Error ( 'Kill process timeout' ) )
169
187
} , timeout * 1000 )
188
+ } else {
189
+ resolve ( )
170
190
}
191
+
192
+ return promise
171
193
}
172
194
173
195
export const parseGrid = ( output : string ) =>
@@ -182,8 +204,8 @@ export const formatOutput = (data: TIngridResponse): TPsLookupEntry[] =>
182
204
const cmd = d . CMD || d . CommandLine || d . COMMAND || [ ]
183
205
184
206
if ( pid && cmd . length > 0 ) {
185
- const c = cmd . findIndex ( ( _v , i ) => isBin ( cmd . slice ( 0 , i ) . join ( '' ) ) ) - 1
186
- const command = cmd . slice ( 0 , c ) . join ( '' )
207
+ const c = ( cmd . findIndex ( ( _v , i ) => isBin ( cmd . slice ( 0 , i ) . join ( ' ' ) ) ) )
208
+ const command = cmd . slice ( 0 , c ) . join ( ' ' )
187
209
const args = cmd . length > 1 ? cmd . slice ( c ) : [ ]
188
210
189
211
m . push ( {
@@ -197,4 +219,15 @@ export const formatOutput = (data: TIngridResponse): TPsLookupEntry[] =>
197
219
return m
198
220
} , [ ] )
199
221
200
- export default { lookup, kill }
222
+ export type PromiseResolve < T = any > = ( value ?: T | PromiseLike < T > ) => void
223
+
224
+ export const makeDeferred = < T = any , E = any > ( ) : { promise : Promise < T > , resolve : PromiseResolve < T > , reject : PromiseResolve < E > } => {
225
+ let resolve
226
+ let reject
227
+ const promise = new Promise < T > ( ( res , rej ) => { resolve = res ; reject = rej } )
228
+ return { resolve, reject, promise } as any
229
+ }
230
+
231
+ export const noop = ( ) => { /* noop */ }
232
+
233
+ export const identity = < T > ( v : T ) : T => v
0 commit comments