aboutsummaryrefslogtreecommitdiff
path: root/lib/compile-handler.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compile-handler.js')
-rw-r--r--lib/compile-handler.js207
1 files changed, 0 insertions, 207 deletions
diff --git a/lib/compile-handler.js b/lib/compile-handler.js
deleted file mode 100644
index 0e506ea0f..000000000
--- a/lib/compile-handler.js
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright (c) 2012-2017, Matt Godbolt
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
-var child_process = require('child_process'),
- temp = require('temp'),
- fs = require('fs'),
- path = require('path'),
- httpProxy = require('http-proxy'),
- denodeify = require('denodeify'),
- quote = require('shell-quote'),
- _ = require('underscore-node'),
- logger = require('./logger').logger,
- utils = require('./utils'),
- CompilationEnvironment = require('./compilation-env').CompilationEnvironment,
- Raven = require('raven');
-
-temp.track();
-
-var oneTimeInit = false;
-
-function initialise(gccProps, compilerEnv) {
- if (oneTimeInit) return;
- oneTimeInit = true;
- var tempDirCleanupSecs = gccProps("tempDirCleanupSecs", 600);
- logger.info("Cleaning temp dirs every " + tempDirCleanupSecs + " secs");
- setInterval(function () {
- if (compilerEnv.isBusy()) {
- logger.warn("Skipping temporary file clean up as compiler environment is busy");
- return;
- }
- temp.cleanup(function (err, stats) {
- if (err) logger.error("Error cleaning directories: ", err);
- if (stats) logger.debug("Directory cleanup stats:", stats);
- });
- }, tempDirCleanupSecs * 1000);
-}
-
-function CompileHandler(gccProps, compilerProps) {
- this.compilersById = {};
- this.compilerEnv = new CompilationEnvironment(gccProps, compilerProps);
- initialise(gccProps, this.compilerEnv);
- this.factories = {};
- this.stat = denodeify(fs.stat);
-
- this.create = function (compiler) {
- var type = compiler.compilerType || "default";
- if (this.factories[type] === undefined) {
- var compilerPath = './compilers/' + type;
- logger.info("Loading compiler from", compilerPath);
- this.factories[type] = require(compilerPath);
- }
- if (path.isAbsolute(compiler.exe)) {
- // Try stat'ing the compiler to cache its mtime and only re-run it if it
- // has changed since the last time.
- return this.stat(compiler.exe)
- .then(_.bind(function (res) {
- var cached = this.compilersById[compiler.id];
- if (cached && cached.mtime.getTime() === res.mtime.getTime()) {
- logger.debug(compiler.id + " is unchanged");
- return cached;
- }
- return this.factories[type](compiler, this.compilerEnv)
- .then(function (compiler) {
- if (compiler) compiler.mtime = res.mtime;
- return compiler;
- });
- }, this))
- .catch(function (err) {
- logger.warn("Unable to stat compiler binary", err);
- return null;
- });
- } else {
- return this.factories[type](compiler, this.compilerEnv);
- }
- };
-
- this.setCompilers = function (compilers) {
- return Promise.all(_.map(compilers, this.create, this))
- .then(_.compact)
- .then(compilers => {
- _.each(compilers, compiler => this.compilersById[compiler.compiler.id] = compiler);
- return _.map(compilers, compiler => compiler.getInfo());
- })
- .catch(err => logger.error(err));
- };
- var proxy = httpProxy.createProxyServer({});
- var textBanner = compilerProps('textBanner');
-
- this.handler = _.bind(function compile(req, res, next) {
- var source, options, backendOptions, filters, compiler;
- if (req.is('json')) {
- // JSON-style request
- compiler = this.compilersById[req.compiler || req.body.compiler];
- if (!compiler) return next();
- var requestOptions = req.body.options;
- source = req.body.source;
- options = requestOptions.userArguments;
- backendOptions = requestOptions.compilerOptions;
- filters = requestOptions.filters || compiler.getDefaultFilters();
- } else {
- // API-style
- compiler = this.compilersById[req.compiler];
- if (!compiler) return next();
- source = req.body;
- options = req.query.options;
- // By default we get the default filters.
- filters = compiler.getDefaultFilters();
- // If specified exactly, we'll take that with ?filters=a,b,c
- if (req.query.filters) {
- filters = _.object(_.map(req.query.filters.split(","), function (filter) {
- return [filter, true];
- }));
- }
- // Add a filter. ?addFilters=binary
- _.each((req.query.addFilters || "").split(","), function (filter) {
- filters[filter] = true;
- });
- // Remove a filter. ?removeFilter=intel
- _.each((req.query.removeFilters || "").split(","), function (filter) {
- delete filters[filter];
- });
- }
- var remote = compiler.getRemote();
- if (remote) {
- req.url = req.originalUrl; // Undo any routing that was done to get here (i.e. /api/* path has been removed)
- proxy.web(req, res, {target: remote}, function (e) {
- logger.error("Proxy error: ", e);
- next(e);
- });
- return;
- }
-
- if (source === undefined) {
- return next(new Error("Bad request"));
- }
- options = _.chain(quote.parse(options || '')
- .map(x => typeof(x) === "string" ? x : x.pattern))
- .compact()
- .value();
-
- function textify(array) {
- return _.pluck(array || [], 'text').join("\n");
- }
-
- compiler.compile(source, options, backendOptions, filters).then(
- function (result) {
- if (req.accepts(['text', 'json']) === 'json') {
- res.set('Content-Type', 'application/json');
- res.end(JSON.stringify(result));
- } else {
- res.set('Content-Type', 'text/plain');
- try {
- if (!_.isEmpty(textBanner)) res.write('# ' + textBanner + "\n");
- res.write(textify(result.asm));
- if (result.code !== 0) res.write("\n# Compiler exited with result code " + result.code);
- if (!_.isEmpty(result.stdout)) res.write("\nStandard out:\n" + textify(result.stdout));
- if (!_.isEmpty(result.stderr)) res.write("\nStandard error:\n" + textify(result.stderr));
- } catch (ex) {
- Raven.captureException(ex, {req: req});
- res.write("Error handling request: " + ex);
- }
- res.end('\n');
- }
- },
- function (error) {
- logger.error("Error during compilation", error);
- if (typeof(error) !== "string") {
- if (error.code) {
- if (typeof(error.stderr) === "string") {
- error.stdout = utils.parseOutput(error.stdout);
- error.stderr = utils.parseOutput(error.stderr);
- }
- res.end(JSON.stringify(error));
- return;
- }
- error = "Internal Compiler Explorer error: " + (error.stack || error);
- }
- res.end(JSON.stringify({code: -1, stderr: [{text: error}]}));
- }
- );
- }, this);
-}
-
-module.exports = {
- CompileHandler: CompileHandler
-};