$Title Test asynchronous execution at compile and execution time (ASYNEXEC,SEQ=515) $ontext In this test GAMS jobs are started asynchronous. Afterwards it is demonstrated how to either wait for completion or send a kill signal to those jobs. There are three ways to start a job asynchronously: > $Call.ASync ... > Execute.ASync '...'; > put_utility fx 'Exec.ASync' / '...'; / put_utility fx 'Shell.ASync' / '...'; After each of those the function JobHandle could be used to get the Process ID of the last job executed. With JobStatus(pid) one could check for the status of a job. Possible return values are: 0: error (input is not a valid PID or access is denied) 1: process is still running 2: process is finished with return code which could be accessed by errorlevel 3: process not running anymore or was never running, no return code available With JobTerminate(pid) a interrupt signal can be send to a running job. If this was successful the return value is one, otherwise it is zero. With JobKill(pid) a kill signal can be send to a running job. If this was successful the return value is one, otherwise it is zero. Contributor: L. Westermann $offtext $call gamslib -q trnsport $onecho > sleep.gms $if not set secs $set secs 0 display$sleep(%secs%) 'Sleep %secs% seconds' $offecho $Call.ASync gams sleep --secs 3 lo=%GAMS.lo% $eval jh JobHandle $set jh2 %system.JobHandle% $if not %jh% == %jh2% $abort JobHandle <> system.JobHandle $log >>> JobHandle : %jh% $label loopstart1 $eval status JobStatus(%jh%) $log >>> Status : %status% $if not %status% == 1 $goto loopdone1 $call sleep 1 $goto loopstart1 $label loopdone1 $if not %status% == 2 $abort '*** $Call.ASync gams... failed: wrong status' $if errorlevel 1 $abort '*** $Call.ASync gams... failed: wrong errorlevel' $Call.ASync =gams sleep --secs 3 lo=%GAMS.lo% $eval jh JobHandle $log >>> JobHandle : %jh% $label loopstart2 $eval status JobStatus(%jh%) $log >>> Status : %status% $if not %status% == 1 $goto loopdone2 $call sleep 1 $goto loopstart2 $label loopdone2 $if not %status% == 2 $abort '*** $Call.ASync =gams... failed: wrong status' $if errorlevel 1 $abort '*** $Call.ASync =gams... failed: wrong errorlevel' file fx; scalar jh,kill,status /1/; Execute.ASync 'gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); abort$(status <> 2) '*** Execute.ASync gams... failed: wrong status'; abort$errorlevel '*** Execute.ASync gams... failed: wrong errorlevel'; Execute.ASync '=gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; status = 1; put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); abort$(status <> 2) '*** Execute.ASync =gams... failed: wrong status'; abort$errorlevel '*** Execute.ASync =gams... failed: wrong errorlevel'; put_utility fx 'Exec.ASync' / 'gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; status = 1; put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); abort$(status <> 2) '*** Exec.ASync gams... failed: wrong status'; abort$errorlevel '*** Exec.ASync gams... failed: wrong errorlevel'; put_utility fx 'Shell.ASync' / 'gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; status = 1; put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); abort$(status <> 2) '*** Shell.ASync gams... failed: wrong status'; abort$errorlevel '*** Shell.ASync gams... failed: wrong errorlevel'; $Call.ASync =gams sleep --secs 3 lo=%GAMS.lo% $eval jh JobHandle $log >>> JobHandle : %jh% $eval status JobStatus(%jh%) $log >>> Status : %status% $eval kill JobKill(%jh%) $log >>> Kill RC : %kill% $if %kill% == 0 $abort '*** compile time JobKill failed: kill returns error' $eval status JobStatus(%jh%) $log >>> Status : %status% $ifthen %status% == 1 $call sleep 1 $eval status JobStatus(%jh%) $log >>> Status : %status% $endif $if %status% == 1 $abort '*** compile time JobKill failed: process not killed' Execute.ASync '=gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; put_utility fx 'log' / '>>> JobHandle :' jh; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; kill = JobKill(jh); put_utility fx 'log' / '>>> Kill RC :' kill; abort$(kill=0) '*** execution time JobKill failed: kill returns error'; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; if(status=1, display$sleep(1) 'sleep some'; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; ); abort$(status=1) '*** execution time JobKill failed: process not killed'; Execute.ASync 'gams sleep --secs 8 lo=%GAMS.lo%'; jh = JobHandle; put_utility fx 'log' / '>>> JobHandle :' jh; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; option solvelink=%solvelink.chainscript%; $include trnsport.gms put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); $if %system.filesys% == UNIX abort$(status <> 3) '*** Recollect after solve failed: wrong status'; $if not %system.filesys% == UNIX abort$(status <> 2) '*** Recollect after solve failed: wrong status'; $if not %system.filesys% == UNIX abort$errorlevel '*** Recollect after solve failed: wrong errorlevel'; $onecho > SpawnJob.gms $set flags mip=scip iterlim=30000 lo=2 file fx, fy /pid.inc/; scalar jh,kill,status /1/; Execute.ASync '=gams sleep --secs 3 lo=%GAMS.lo%'; jh = JobHandle; put_utility fx 'log' / '>>> JobHandle :' jh; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; putclose fy jh:0:0; $offecho $call gams SpawnJob lo=%GAMS.lo% $onecho > CollectJob.gms file fx; scalar kill,status /1/; scalar jh / $include pid.inc /; put_utility fx 'log' / '>>> JobHandle :' jh; while(status = 1, status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; display$sleep(1$(status=1)) 'sleep some'; ); $if %system.filesys% == UNIX abort$(status <> 3) '*** Collect Handle failed: wrong status'; $if not %system.filesys% == UNIX abort$(status <> 2) '*** Collect Handle failed: wrong status'; $if not %system.filesys% == UNIX abort$errorlevel '*** Collect Handle failed: wrong errorlevel'; $offecho $call gams CollectJob lo=%GAMS.lo% $if errorlevel 1 $abort '*** Collect Handle failed' $exit *This needs some work to have something running on all platforms Execute.ASync 'garbage dice %flags%'; jh = JobHandle; put_utility fx 'log' / '>>> JobHandle :' jh; status = JobStatus(jh); put_utility fx 'log' / '>>> Status :' status; abort$(Status<>0) '*** Should get an error when spawning garbage';