@@ -79,12 +79,16 @@ class Worker extends EventEmitter {
7979 if ( options . execArgv && ! Array . isArray ( options . execArgv ) )
8080 throw new ArgError ( 'execArgv' , options . execArgv , 'Array' ) ;
8181
82+ if ( options . resourceLimits && typeof options . resourceLimits !== 'object' )
83+ throw new ArgError ( 'resourceLimits' , options . resourceLimits , 'object' ) ;
84+
8285 this . _child = null ;
8386 this . _parser = new Parser ( this ) ;
8487 this . _ports = new Map ( ) ;
8588 this . _writable = true ;
8689 this . _exited = false ;
8790 this . _killed = false ;
91+ this . _limits = false ;
8892 this . _exitCode = - 1 ;
8993 this . _stdioRef = null ;
9094 this . _stdioRefs = 0 ;
@@ -104,6 +108,7 @@ class Worker extends EventEmitter {
104108
105109 _init ( file , options ) {
106110 const bin = process . execPath || process . argv [ 0 ] ;
111+ const limits = options . resourceLimits ;
107112 const args = [ ] ;
108113
109114 // Validate filename.
@@ -181,6 +186,24 @@ class Worker extends EventEmitter {
181186 }
182187 }
183188
189+ // Enforce resource limits.
190+ if ( limits ) {
191+ const maxOld = limits . maxOldSpaceSizeMb ;
192+ const maxSemi = limits . maxSemiSpaceSizeMb ;
193+
194+ if ( typeof maxOld === 'number' ) {
195+ args . push ( `--max-old-space-size=${ Math . max ( maxOld , 2 ) } ` ) ;
196+ this . _limits = true ;
197+ }
198+
199+ if ( typeof maxSemi === 'number' ) {
200+ args . push ( `--max-semi-space-size=${ maxSemi } ` ) ;
201+ this . _limits = true ;
202+ }
203+
204+ // Todo: figure out how to do codeRangeSizeMb.
205+ }
206+
184207 // Require bthreads on boot, but make
185208 // sure we're not bundled or something.
186209 if ( ! hasRequireArg ( args , __dirname ) ) {
@@ -298,7 +321,18 @@ class Worker extends EventEmitter {
298321 } ) ;
299322
300323 this . _parser . on ( 'error' , ( err ) => {
301- this . emit ( 'error' , err ) ;
324+ this . _parser . destroy ( ) ;
325+
326+ if ( this . _limits ) {
327+ // Probably an OOM:
328+ // v8 writes the last few GC attempts to stdout,
329+ // and then writes some debugging info to stderr.
330+ this . emit ( 'error' , new WorkerError ( errors . OUT_OF_MEMORY ) ) ;
331+ } else {
332+ this . emit ( 'error' , err ) ;
333+ }
334+
335+ this . _kill ( 1 ) ;
302336 } ) ;
303337
304338 this . _parser . on ( 'packet' , ( pkt ) => {
@@ -403,6 +437,9 @@ class Worker extends EventEmitter {
403437 }
404438
405439 _handleExit ( code , signal ) {
440+ if ( signal === 'SIGABRT' )
441+ code = 1 ;
442+
406443 // Child was terminated with signal handler.
407444 if ( code === 143 && signal == null ) {
408445 // Convert to SIGTERM signal.
0 commit comments