@@ -9,11 +9,8 @@ import * as cp from 'child_process';
99import ChildProcess = cp . ChildProcess ;
1010import exec = cp . exec ;
1111import spawn = cp . spawn ;
12-
1312import { PassThrough } from 'stream' ;
14-
15- import { fork } from './stdFork' ;
16-
13+ import { fork } from 'vs/base/node/stdFork' ;
1714import nls = require( 'vs/nls' ) ;
1815import { PPromise , Promise , TPromise , TValueCallback , TProgressCallback , ErrorCallback } from 'vs/base/common/winjs.base' ;
1916import * as Types from 'vs/base/common/types' ;
@@ -22,7 +19,6 @@ import URI from 'vs/base/common/uri';
2219import * as Objects from 'vs/base/common/objects' ;
2320import * as TPath from 'vs/base/common/paths' ;
2421import * as Platform from 'vs/base/common/platform' ;
25-
2622import { LineDecoder } from 'vs/base/node/decoder' ;
2723import { CommandOptions , ForkOptions , SuccessData , Source , TerminateResponse , TerminateResponseCode , Executable } from 'vs/base/common/processes' ;
2824export { CommandOptions , ForkOptions , SuccessData , Source , TerminateResponse , TerminateResponseCode } ;
@@ -447,4 +443,46 @@ export class StreamProcess extends AbstractProcess<StreamData> {
447443 pp ( { stdin : childProcess . stdin , stdout : childProcess . stdout , stderr : childProcess . stderr } ) ;
448444 }
449445 }
446+ }
447+
448+ export interface IQueuedSender {
449+ send : ( msg : any ) => void ;
450+ }
451+
452+ // Wrapper around process.send() that will queue any messages if the internal node.js
453+ // queue is filled with messages and only continue sending messages when the internal
454+ // queue is free again to consume messages.
455+ // On Windows we always wait for the send() method to return before sending the next message
456+ // to workaround https://github.com/nodejs/node/issues/7657 (IPC can freeze process)
457+ export function createQueuedSender ( childProcess : ChildProcess | NodeJS . Process ) : IQueuedSender {
458+ let msgQueue = [ ] ;
459+ let useQueue = false ;
460+
461+ const send = function ( msg : any ) : void {
462+ if ( useQueue ) {
463+ msgQueue . push ( msg ) ; // add to the queue if the process cannot handle more messages
464+ return ;
465+ }
466+
467+ let result = childProcess . send ( msg , error => {
468+ if ( error ) {
469+ console . error ( error ) ; // unlikely to happen, best we can do is log this error
470+ }
471+
472+ useQueue = false ; // we are good again to send directly without queue
473+
474+ // now send all the messages that we have in our queue and did not send yet
475+ if ( msgQueue . length > 0 ) {
476+ const msgQueueCopy = msgQueue . slice ( 0 ) ;
477+ msgQueue = [ ] ;
478+ msgQueueCopy . forEach ( entry => send ( entry ) ) ;
479+ }
480+ } ) ;
481+
482+ if ( ! result || Platform . isWindows /* workaround https://github.com/nodejs/node/issues/7657 */ ) {
483+ useQueue = true ;
484+ }
485+ } ;
486+
487+ return { send } ;
450488}
0 commit comments