diff --git a/README.md b/README.md index 39060eae4..81d508114 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,7 @@ Both `.provider()` and `.server()` take a single object which allows you to spec * `"gasLimit"`: `String::hex | number` Sets the block gas limit. Must be specified as a `hex` string or `number`. Defaults to `"0x6691b7"`. * `"callGasLimit"`: `number` Sets the transaction gas limit for `eth_call` and `eth_estimateGas` calls. Must be specified as a `hex` string. Defaults to `"0x1fffffffffffff"` (`Number.MAX_SAFE_INTEGER`). * `"keepAliveTimeout"`: `number` If using `.server()` - Sets the HTTP server's `keepAliveTimeout` in milliseconds. See the [NodeJS HTTP docs](https://nodejs.org/api/http.html#http_server_keepalivetimeout) for details. `5000` by default. +* `"deasync"`: `boolean` Synchronizes ganache server startup. Useful in certain scenarios - see ganache-cli issue [#733](https://github.com/trufflesuite/ganache-cli/issues/733). ## Implemented Methods diff --git a/args.js b/args.js index dac4a1a8a..912191c15 100644 --- a/args.js +++ b/args.js @@ -205,6 +205,12 @@ module.exports = exports = function(yargs, version, isDocker) { type: 'boolean', default: false }) + .option('deasync', { + group: 'Other::', + describe: 'Synchronize ganache server startup. Useful in certain scenarios (see ganache-cli issue #733).', + type: 'boolean', + default: false + }) .showHelpOnFail(false, 'Specify -? or --help for available options') .help('help') .alias('help', '?') diff --git a/cli.js b/cli.js index ec77da2ee..90d34883c 100755 --- a/cli.js +++ b/cli.js @@ -21,6 +21,12 @@ var detailedVersion = "Ganache CLI v" + pkg.version + " (ganache-core: " + ganac var isDocker = "DOCKER" in process.env && process.env.DOCKER.toLowerCase() === "true"; var argv = initArgs(yargs, detailedVersion, isDocker).argv; +var deasync; +try { + deasync = argv.deasync ? require("deasync") : false; +} catch(e) { + deasync = false; +} function parseAccounts(accounts) { function splitAccount(account) { @@ -106,12 +112,54 @@ var server = ganache.server(options); console.log(detailedVersion); -server.listen(options.port, options.hostname, function(err, result) { +let started = false; +process.on("uncaughtException", function(e) { + if (started) { + console.log(e); + } else { + console.log(e.stack); + } + process.exit(1); +}) + +// See http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js +if (process.platform === "win32") { + require("readline").createInterface({ + input: process.stdin, + output: process.stdout + }) + .on("SIGINT", function () { + process.emit("SIGINT"); + }); +} + +const closeHandler = function () { + // graceful shutdown + server.close(function(err) { + if (err) { + // https://nodejs.org/api/process.html#process_process_exit_code + // writes to process.stdout in Node.js are sometimes asynchronous and may occur over + // multiple ticks of the Node.js event loop. Calling process.exit(), however, forces + // the process to exit before those additional writes to stdout can be performed. + if(process.stdout._handle) process.stdout._handle.setBlocking(true); + console.log(err.stack || err); + process.exit(); + } else { + process.exit(0); + } + }); +} + +process.on("SIGINT", closeHandler); +process.on("SIGTERM", closeHandler); +process.on("SIGHUP", closeHandler); + +function startGanache(err, result) { if (err) { console.log(err); return; } - + started = true; var state = result ? result : server.provider.manager.state; console.log(""); @@ -190,41 +238,12 @@ server.listen(options.port, options.hostname, function(err, result) { console.log(""); console.log("Listening on " + options.hostname + ":" + options.port); -}); - -process.on('uncaughtException', function(e) { - console.log(e.stack); - process.exit(1); -}) - -// See http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js -if (process.platform === "win32") { - require("readline").createInterface({ - input: process.stdin, - output: process.stdout - }) - .on("SIGINT", function () { - process.emit("SIGINT"); - }); } -const closeHandler = function () { - // graceful shutdown - server.close(function(err) { - if (err) { - // https://nodejs.org/api/process.html#process_process_exit_code - // writes to process.stdout in Node.js are sometimes asynchronous and may occur over - // multiple ticks of the Node.js event loop. Calling process.exit(), however, forces - // the process to exit before those additional writes to stdout can be performed. - if(process.stdout._handle) process.stdout._handle.setBlocking(true); - console.log(err.stack || err); - process.exit(); - } else { - process.exit(0); - } - }); +if (deasync) { + const listen = deasync(server.listen); + const result = listen(options.port, options.hostname); + startGanache(null, result); +} else { + server.listen(options.port, options.hostname, startGanache); } - -process.on("SIGINT", closeHandler); -process.on("SIGTERM", closeHandler); -process.on("SIGHUP", closeHandler); diff --git a/package-lock.json b/package-lock.json index 398592a79..fdd081f89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -933,6 +933,15 @@ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, + "deasync": { + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.20.tgz", + "integrity": "sha512-E1GI7jMI57hL30OX6Ht/hfQU8DO4AuB9m72WFm4c38GNbUD4Q03//XZaOIHZiY+H1xUaomcot5yk2q/qIZQkGQ==", + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -17255,6 +17264,11 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "node-addon-api": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", + "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==" + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", diff --git a/package.json b/package.json index 33e46251a..32de7def9 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,9 @@ "webpack": "^4.18.0", "webpack-cli": "3.1.0" }, + "optionalDependencies": { + "deasync": "0.1.20" + }, "repository": { "type": "git", "url": "https://github.com/trufflesuite/ganache-cli"