Просмотр исходного кода

kill process group on timeout of convert commands

Brian Gough 11 лет назад
Родитель
Сommit
33d8974d02

+ 4 - 5
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

+ 40 - 0
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