api: tidy up execute

This commit is contained in:
Thomas Hobson 2021-02-22 21:55:51 +13:00
parent 3e6fac5c0e
commit 00bb5be55b
No known key found for this signature in database
GPG Key ID: 9F1FD9D87950DB6F
1 changed files with 25 additions and 47 deletions

View File

@ -68,80 +68,58 @@ class Job {
logger.debug('Primed job'); logger.debug('Primed job');
} }
async execute(){ async safe_call(file, args){
if(this.state != job_states.PRIMED) throw new Error('Job must be in primed state, current state: ' + this.state.toString()); return await new Promise((resolve, reject) => {
logger.info(`Executing job uuid=${this.uuid} uid=${this.uid} gid=${this.gid} runtime=${this.runtime.toString()}`); const proc_call = ['bash',file, ...args]
logger.debug('Compiling');
const compile = this.runtime.compiled && await new Promise((resolve, reject) => {
const proc_call = ['unshare', '-n', '-r', 'bash', path.join(this.runtime.pkgdir, 'compile'),this.main, ...this.files].slice(!config.enable_unshare * 3)
var stdout = ''; var stdout = '';
var stderr = ''; var stderr = '';
const proc = cp.spawn(proc_call[0], proc_call.splice(1) ,{ const proc = cp.spawn(proc_call[0], proc_call.splice(1) ,{
env: this.runtime.env_vars, env: this.runtime.env_vars,
stdio: ['pipe', 'pipe', 'pipe'], stdio: 'pipe',
cwd: this.dir, cwd: this.dir,
uid: this.uid, uid: this.uid,
gid: this.gid gid: this.gid,
detached: true //dont kill the main process when we kill the group
}); });
const kill_timeout = setTimeout(_ => proc.kill('SIGKILL'), this.timeouts.compile); const kill_timeout = setTimeout(_ => proc.kill('SIGKILL'), this.timeouts.compile);
proc.stderr.on('data', d=>{if(stderr.length>config.output_max_size) proc.kill('SIGKILL'); else stderr += d;}); proc.stderr.on('data', d=>{if(stderr.length>config.output_max_size) proc.kill('SIGKILL'); else stderr += d;});
proc.stdout.on('data', d=>{if(stdout.length>config.output_max_size) proc.kill('SIGKILL'); else stdout += d;}); proc.stdout.on('data', d=>{if(stdout.length>config.output_max_size) proc.kill('SIGKILL'); else stdout += d;});
function exitCleanup(){
proc.on('exit', (code, signal)=>{
clearTimeout(kill_timeout); clearTimeout(kill_timeout);
proc.stderr.destroy() proc.stderr.destroy()
proc.stdout.destroy() proc.stdout.destroy()
try{
process.kill(-proc.pid, 'SIGKILL')
}catch{} //Probably already dead!
}
proc.on('exit', (code, signal)=>{
exitCleanup()
resolve({stdout, stderr, code, signal}); resolve({stdout, stderr, code, signal});
}); });
proc.on('error', (err) => { proc.on('error', (err) => {
clearTimeout(kill_timeout); exitCleanup()
proc.stderr.destroy()
proc.stdout.destroy()
reject({error: err, stdout, stderr}); reject({error: err, stdout, stderr});
}); });
}); });
}
async execute(){
if(this.state != job_states.PRIMED) throw new Error('Job must be in primed state, current state: ' + this.state.toString());
logger.info(`Executing job uuid=${this.uuid} uid=${this.uid} gid=${this.gid} runtime=${this.runtime.toString()}`);
logger.debug('Compiling');
const compile = this.runtime.compiled && await this.safe_call(path.join(this.runtime.pkgdir, 'compile'), [this.main, ...this.files])
logger.debug('Running'); logger.debug('Running');
const run = await new Promise((resolve, reject) => { const run = await this.safe_call(path.join(this.runtime.pkgdir, 'run'), [this.main, ...this.args])
const proc_call = ['unshare', '-n', '-r', 'bash', path.join(this.runtime.pkgdir, 'run'), this.main, ...this.args].slice(!config.enable_unshare * 3);
var stdout = '';
var stderr = '';
const proc = cp.spawn(proc_call[0], proc_call.slice(1) ,{
env: this.runtime.env_vars,
stdio: ['pipe', 'pipe', 'pipe'],
cwd: this.dir,
uid: this.uid,
gid: this.gid
});
const kill_timeout = setTimeout(_ => proc.kill('SIGKILL'), this.timeouts.run);
proc.stderr.on('data', d=>{if(stderr.length>config.output_max_size) proc.kill('SIGKILL'); else stderr += d;});
proc.stdout.on('data', d=>{if(stdout.length>config.output_max_size) proc.kill('SIGKILL'); else stdout += d;});
proc.stdin.write(this.stdin)
proc.stdin.end()
proc.on('exit', (code, signal)=>{
clearTimeout(kill_timeout);
proc.stderr.destroy()
proc.stdout.destroy()
resolve({stdout, stderr, code, signal});
});
proc.on('error', (err) => {
clearTimeout(kill_timeout);
proc.stderr.destroy()
proc.stdout.destroy()
reject({error: err, stdout, stderr});
});
});
this.state = job_states.EXECUTED; this.state = job_states.EXECUTED;