diff --git a/services/filestore/app/coffee/FileConverter.coffee b/services/filestore/app/coffee/FileConverter.coffee index 0d6eb0d9f3..d791e4c2d0 100644 --- a/services/filestore/app/coffee/FileConverter.coffee +++ b/services/filestore/app/coffee/FileConverter.coffee @@ -1,7 +1,7 @@ _ = require("underscore") metrics = require("metrics-sharelatex") logger = require("logger-sharelatex") -exec = require('child_process').exec +safe_exec = require('./SafeExec') approvedFormats = ["png"] fourtySeconds = 40 * 1000 @@ -23,8 +23,7 @@ module.exports = return callback err width = "600x" args = "nice convert -define pdf:fit-page=#{width} -flatten -density 300 #{sourcePath} #{destPath}" - console.log args - exec args, childProcessOpts, (err, stdout, stderr)-> + safe_exec args, childProcessOpts, (err, stdout, stderr)-> timer.done() if err? logger.err err:err, stderr:stderr, sourcePath:sourcePath, requestedFormat:requestedFormat, destPath:destPath, "something went wrong converting file" @@ -38,7 +37,7 @@ module.exports = sourcePath = "#{sourcePath}[0]" width = "260x" args = "nice convert -flatten -background white -density 300 -define pdf:fit-page=#{width} #{sourcePath} -resize #{width} #{destPath}" - exec args, childProcessOpts, (err, stdout, stderr)-> + safe_exec args, childProcessOpts, (err, stdout, stderr)-> if err? logger.err err:err, stderr:stderr, sourcePath:sourcePath, "something went wrong converting file to preview" else @@ -51,7 +50,7 @@ module.exports = sourcePath = "#{sourcePath}[0]" width = "548x" args = "nice convert -flatten -background white -density 300 -define pdf:fit-page=#{width} #{sourcePath} -resize #{width} #{destPath}" - exec args, childProcessOpts, (err, stdout, stderr)-> + safe_exec args, childProcessOpts, (err, stdout, stderr)-> if err? logger.err err:err, stderr:stderr, sourcePath:sourcePath, destPath:destPath, "something went wrong converting file to preview" else diff --git a/services/filestore/app/coffee/SafeExec.coffee b/services/filestore/app/coffee/SafeExec.coffee new file mode 100644 index 0000000000..65da163538 --- /dev/null +++ b/services/filestore/app/coffee/SafeExec.coffee @@ -0,0 +1,40 @@ +_ = require("underscore") +logger = require("logger-sharelatex") +child_process = require('child_process') + +# execute a command in the same way as 'exec' but with a timeout that +# kills all child processes +# +# we spawn the command with 'detached:true' to make a new process +# group, then we can kill everything in that process group. + +module.exports = (command, options, callback = (err, stdout, stderr) ->) -> + [cmd, args...] = command.split(' ') + + child = child_process.spawn cmd, args, {detached:true} + stdout = "" + stderr = "" + + cleanup = _.once (err) -> + clearTimeout killTimer if killTimer? + callback err, stdout, stderr + + if options.timeout? + killTimer = setTimeout () -> + try + process.kill -child.pid, options.killSignal || "SIGTERM" + catch error + logger.log process: child.pid, kill_error: error, "error killing process" + , options.timeout + + child.on 'exit', (code, signal) -> + cleanup signal + + child.on 'error', (err) -> + cleanup err + + child.stdout.on 'data', (chunk) -> + stdout += chunk + + child.stderr.on 'data', (chunk) -> + stderr += chunk