@@ -24,6 +24,25 @@ import { localize } from 'vs/nls';
24
24
const WRITE_MAX_CHUNK_SIZE = 50 ;
25
25
const WRITE_INTERVAL_MS = 5 ;
26
26
27
+ const enum ShutdownConstants {
28
+ /**
29
+ * The amount of time that must pass between data events after exit is queued before the actual
30
+ * kill call is triggered. This data flush mechanism works around an [issue in node-pty][1]
31
+ * where not all data is flushed which causes problems for task problem matchers. Additionally
32
+ * on Windows under conpty, killing a process while data is being output will cause the [conhost
33
+ * flush to hang the pty host][2] because [conhost should be hosted on another thread][3].
34
+ *
35
+ * [1]: https://github.com/Tyriar/node-pty/issues/72
36
+ * [2]: https://github.com/microsoft/vscode/issues/71966
37
+ * [3]: https://github.com/microsoft/node-pty/pull/415
38
+ */
39
+ DataFlushTimeout = 250 ,
40
+ /**
41
+ * The maximum time to allow after dispose is called because forcefully killing the process.
42
+ */
43
+ MaximumShutdownTime = 5000
44
+ }
45
+
27
46
export class TerminalProcess extends Disposable implements ITerminalChildProcess {
28
47
readonly id = 0 ;
29
48
readonly shouldPersist = false ;
@@ -223,7 +242,10 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
223
242
if ( this . _closeTimeout ) {
224
243
clearTimeout ( this . _closeTimeout ) ;
225
244
}
226
- this . _closeTimeout = setTimeout ( ( ) => this . _kill ( ) , 250 ) ;
245
+ this . _closeTimeout = setTimeout ( ( ) => {
246
+ this . _closeTimeout = undefined ;
247
+ this . _kill ( ) ;
248
+ } , ShutdownConstants . DataFlushTimeout ) ;
227
249
}
228
250
229
251
private async _kill ( ) : Promise < void > {
@@ -263,7 +285,16 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
263
285
if ( immediate ) {
264
286
this . _kill ( ) ;
265
287
} else {
266
- this . _queueProcessExit ( ) ;
288
+ if ( ! this . _closeTimeout && ! this . _isDisposed ) {
289
+ this . _queueProcessExit ( ) ;
290
+ // Allow a maximum amount of time for the process to exit, otherwise force kill it
291
+ setTimeout ( ( ) => {
292
+ if ( this . _closeTimeout && ! this . _isDisposed ) {
293
+ this . _closeTimeout = undefined ;
294
+ this . _kill ( ) ;
295
+ }
296
+ } , ShutdownConstants . MaximumShutdownTime ) ;
297
+ }
267
298
}
268
299
}
269
300
0 commit comments