2020-02-19 06:14:28 -05:00
|
|
|
/* eslint-disable
|
|
|
|
no-return-assign,
|
|
|
|
no-unused-vars,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
2020-02-19 06:14:14 -05:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS101: Remove unnecessary use of Array.from
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
2020-02-19 06:14:37 -05:00
|
|
|
let CommandRunner
|
2024-11-08 05:21:56 -05:00
|
|
|
const { spawn } = require('node:child_process')
|
|
|
|
const { promisify } = require('node:util')
|
2021-04-29 10:30:54 -04:00
|
|
|
const _ = require('lodash')
|
2022-03-01 10:09:36 -05:00
|
|
|
const logger = require('@overleaf/logger')
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2022-05-16 08:38:18 -04:00
|
|
|
logger.debug('using standard command runner')
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
module.exports = CommandRunner = {
|
2020-06-11 11:01:44 -04:00
|
|
|
run(
|
2023-03-22 07:52:39 -04:00
|
|
|
projectId,
|
2020-06-11 11:01:44 -04:00
|
|
|
command,
|
|
|
|
directory,
|
|
|
|
image,
|
|
|
|
timeout,
|
|
|
|
environment,
|
|
|
|
compileGroup,
|
|
|
|
callback
|
|
|
|
) {
|
2020-02-19 06:14:37 -05:00
|
|
|
let key, value
|
2021-10-27 05:49:18 -04:00
|
|
|
callback = _.once(callback)
|
2021-07-13 07:04:48 -04:00
|
|
|
command = Array.from(command).map(arg =>
|
2020-02-19 06:14:37 -05:00
|
|
|
arg.toString().replace('$COMPILE_DIR', directory)
|
|
|
|
)
|
2023-03-22 07:52:39 -04:00
|
|
|
logger.debug({ projectId, command, directory }, 'running command')
|
2020-02-19 06:14:37 -05:00
|
|
|
logger.warn('timeouts and sandboxing are not enabled with CommandRunner')
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
// merge environment settings
|
|
|
|
const env = {}
|
|
|
|
for (key in process.env) {
|
|
|
|
value = process.env[key]
|
|
|
|
env[key] = value
|
|
|
|
}
|
|
|
|
for (key in environment) {
|
|
|
|
value = environment[key]
|
|
|
|
env[key] = value
|
|
|
|
}
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
// run command as detached process so it has its own process group (which can be killed if needed)
|
2022-04-19 05:11:55 -04:00
|
|
|
const proc = spawn(command[0], command.slice(1), {
|
|
|
|
cwd: directory,
|
|
|
|
env,
|
|
|
|
stdio: ['pipe', 'pipe', 'ignore'],
|
|
|
|
})
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
let stdout = ''
|
2021-07-13 07:04:48 -04:00
|
|
|
proc.stdout.setEncoding('utf8').on('data', data => (stdout += data))
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
proc.on('error', function (err) {
|
2020-02-19 06:14:37 -05:00
|
|
|
logger.err(
|
2023-03-22 07:52:39 -04:00
|
|
|
{ err, projectId, command, directory },
|
2020-02-19 06:14:37 -05:00
|
|
|
'error running command'
|
|
|
|
)
|
|
|
|
return callback(err)
|
|
|
|
})
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
proc.on('close', function (code, signal) {
|
2020-02-19 06:14:37 -05:00
|
|
|
let err
|
2023-03-22 07:52:39 -04:00
|
|
|
logger.debug({ code, signal, projectId }, 'command exited')
|
2020-02-19 06:14:37 -05:00
|
|
|
if (signal === 'SIGTERM') {
|
|
|
|
// signal from kill method below
|
|
|
|
err = new Error('terminated')
|
|
|
|
err.terminated = true
|
|
|
|
return callback(err)
|
|
|
|
} else if (code === 1) {
|
|
|
|
// exit status from chktex
|
|
|
|
err = new Error('exited')
|
|
|
|
err.code = code
|
|
|
|
return callback(err)
|
|
|
|
} else {
|
2022-05-16 10:25:49 -04:00
|
|
|
return callback(null, { stdout })
|
2020-02-19 06:14:37 -05:00
|
|
|
}
|
|
|
|
})
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
return proc.pid
|
|
|
|
}, // return process id to allow job to be killed if necessary
|
2020-02-19 06:14:14 -05:00
|
|
|
|
2020-02-19 06:14:37 -05:00
|
|
|
kill(pid, callback) {
|
|
|
|
if (callback == null) {
|
2021-10-27 05:49:18 -04:00
|
|
|
callback = function () {}
|
2020-02-19 06:14:37 -05:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
process.kill(-pid) // kill all processes in group
|
|
|
|
} catch (err) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
return callback()
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:14:37 -05:00
|
|
|
}
|
2022-07-07 08:27:20 -04:00
|
|
|
|
|
|
|
module.exports.promises = {
|
|
|
|
run: promisify(CommandRunner.run),
|
|
|
|
kill: promisify(CommandRunner.kill),
|
|
|
|
}
|