@@ -551,55 +551,97 @@ function compileCode(command, args, cwd) {
551551 */
552552function runProgram ( command , args , stdin = '' , timeout = 3000 ) {
553553 return new Promise ( ( resolve , reject ) => {
554- const process = spawn ( command , args , { cwd : path . dirname ( command ) } ) ;
554+ const shell = 'bash' ;
555+ const wrapperArgs = [
556+ '-c' ,
557+ `ulimit -u 50; ulimit -f 20480; exec "$@"` ,
558+ 'cmd' ,
559+ command ,
560+ ...args
561+ ] ;
555562
556563 let stdout = '' ;
557564 let stderr = '' ;
558565 let finished = false ;
566+ let killedByEvaluator = false ;
567+
568+ const proc = spawn ( shell , wrapperArgs , {
569+ cwd : path . dirname ( command ) ,
570+ detached : true ,
571+ stdio : [ 'pipe' , 'pipe' , 'pipe' ]
572+ } ) ;
573+
574+ // Resource monitor (memory/threads)
575+ const interval = setInterval ( async ( ) => {
576+ try {
577+ // Example: use pidusage or ps to get memory/threads
578+ // let info = await pidusage(proc.pid);
579+ // if (info.memory > 300 * 1024 * 1024 || info.threadCount > 200) {
580+ // killedByEvaluator = true;
581+ // killGroup(proc.pid);
582+ // clearInterval(interval);
583+ // }
584+ } catch ( _ ) { }
585+ } , 100 ) ;
586+
587+ const killGroup = ( pid ) => {
588+ killedByEvaluator = true ;
589+ try { process . kill ( - pid , 'SIGTERM' ) ; } catch ( _ ) { }
590+ setTimeout ( ( ) => { try { process . kill ( - pid , 'SIGKILL' ) ; } catch ( _ ) { } } , 400 ) ;
591+ } ;
559592
560593 const timer = setTimeout ( ( ) => {
561594 if ( ! finished ) {
562- process . kill ( 'SIGTERM' ) ;
563- console . error ( 'Execution timed out.' ) ;
564- reject ( new Error ( 'Execution timed out' ) ) ;
595+ killGroup ( proc . pid ) ;
596+ clearInterval ( interval ) ;
597+ finished = true ;
598+ return reject ( new Error ( 'Execution timed out' ) ) ;
565599 }
566600 } , timeout ) ;
567601
568602 if ( stdin ) {
569- process . stdin . write ( stdin ) ;
603+ proc . stdin . write ( stdin ) ;
570604 }
571- process . stdin . end ( ) ;
572-
573- process . stdout . on ( 'data' , ( data ) => {
574- stdout += data . toString ( ) ;
575- } ) ;
576-
577- process . stderr . on ( 'data' , ( data ) => {
578- stderr += data . toString ( ) ;
579- } ) ;
605+ proc . stdin . end ( ) ;
606+
607+ proc . stdout . on ( 'data' , d => stdout += d . toString ( ) ) ;
608+ proc . stderr . on ( 'data' , d => stderr += d . toString ( ) ) ;
609+
610+ proc . on ( 'close' , ( code , signal ) => {
611+ if ( finished ) return ;
612+
613+ clearTimeout ( timer ) ;
614+ clearInterval ( interval ) ;
615+ finished = true ;
616+
617+ // If killed via signal (timeout/resource limits)
618+ if ( signal || killedByEvaluator ) {
619+ const reason = signal
620+ ? `terminated by signal ${ signal } `
621+ : 'terminated by evaluator' ;
622+ const err = new Error ( `Execution terminated: ${ reason } ` ) ;
623+ err . stdout = stdout ;
624+ err . stderr = stderr ;
625+ return reject ( err ) ;
626+ }
580627
581- process . on ( 'close' , ( code ) => {
582- if ( ! finished ) {
583- clearTimeout ( timer ) ;
584- finished = true ;
585- if ( code !== 0 ) {
586- console . error ( `Execution failed with code ${ code } : stderr: ${ stderr } , stdout: ${ stdout } ` ) ;
587- const error = new Error ( `Execution failed with code ${ code } ` ) ;
588- error . stdout = stdout ;
589- error . stderr = stderr ;
590- return reject ( error ) ;
591- }
592- resolve ( { stdout, stderr } ) ;
628+ // Normal exit code check
629+ if ( code !== 0 ) {
630+ const err = new Error ( `Execution failed with code ${ code } ` ) ;
631+ err . stdout = stdout ;
632+ err . stderr = stderr ;
633+ return reject ( err ) ;
593634 }
635+
636+ resolve ( { stdout, stderr } ) ;
594637 } ) ;
595638
596- process . on ( 'error' , ( err ) => {
597- if ( ! finished ) {
598- clearTimeout ( timer ) ;
599- finished = true ;
600- console . error ( `Failed to start execution process: ${ err . message } ` ) ;
601- reject ( err ) ;
602- }
639+ proc . on ( 'error' , err => {
640+ if ( finished ) return ;
641+ clearTimeout ( timer ) ;
642+ clearInterval ( interval ) ;
643+ finished = true ;
644+ reject ( new Error ( `Failed to start process: ${ err . message } ` ) ) ;
603645 } ) ;
604646 } ) ;
605647}
@@ -610,7 +652,7 @@ function runProgram(command, args, stdin = '', timeout = 3000) {
610652 */
611653async function cleanupDir ( dirPath ) {
612654 try {
613- await fs . rm ( dirPath , { recursive : true , force : true } ) ; // if you really want to delete
655+ await fs . rm ( dirPath , { recursive : true , force : true } ) ;
614656 console . log ( `Successfully deleted directory: ${ dirPath } ` ) ;
615657 } catch ( err ) {
616658 console . error ( `Failed to delete directory ${ dirPath } : ${ err . message } ` ) ;
0 commit comments