mirror of https://github.com/embarklabs/embark.git
feat(@embark/core): store IPC files in a dir within os.tmpdir()
This PR replaces #1202. When embark is running on Linux and macOS, unix socket files are used for geth's and embark's IPC files. A problem can arise if a DApp is in a deeply nested directory structure such that character-length of the path to a socket file exceeds the maximum supported length. See #450. Also, if the DApp context is a Linux container running on a Windows Docker host, and if the DApp is mounted from the host's file system, there is a problem: unix socket files are incompatible with the Windows file system. Solve both problems at once by storing a DApp's `.ipc` files in a directory within `os.tmpdir()`. Introduce `ipcPath()` in `core/fs.js` and use a truncated SHA-512 hash of the DApp's path in the name of the temporary directory created for that purpose so that DApps won't collide (with an acceptably low probability of collision).
This commit is contained in:
parent
9c37f9738e
commit
a91a4dd7c0
|
@ -148,6 +148,19 @@ function diagramPath() {
|
|||
return anchoredPath(env.DIAGRAM_PATH, ...arguments);
|
||||
}
|
||||
|
||||
function ipcPath(basename, usePipePathOnWindows = false) {
|
||||
if (!(basename && typeof basename === 'string')) {
|
||||
throw new TypeError('first argument must be a non-empty string');
|
||||
}
|
||||
if (process.platform === 'win32' && usePipePathOnWindows) {
|
||||
return `\\\\.\\pipe\\${basename}`;
|
||||
}
|
||||
return utils.joinPath(
|
||||
tmpDir(`embark-${utils.sha512(dappPath()).slice(0, 8)}`),
|
||||
basename
|
||||
);
|
||||
}
|
||||
|
||||
function pkgPath() {
|
||||
return anchoredPath(env.PKG_PATH, ...arguments);
|
||||
}
|
||||
|
@ -200,6 +213,7 @@ module.exports = {
|
|||
existsSync,
|
||||
ensureFileSync,
|
||||
ensureDirSync,
|
||||
ipcPath,
|
||||
mkdirp,
|
||||
mkdirpSync,
|
||||
move,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const fs = require('./fs.js');
|
||||
const fs = require('./fs');
|
||||
const ipc = require('node-ipc');
|
||||
const {parse, stringify} = require('flatted/cjs');
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
class IPC {
|
||||
|
||||
constructor(options) {
|
||||
this.logger = options.logger;
|
||||
this.socketPath = options.socketPath || fs.dappPath(".embark/embark.ipc");
|
||||
this.socketPath = options.socketPath || fs.ipcPath('embark.ipc');
|
||||
this.ipcRole = options.ipcRole;
|
||||
ipc.config.silent = true;
|
||||
this.connected = false;
|
||||
|
@ -39,7 +39,7 @@ class IPC {
|
|||
}
|
||||
|
||||
serve() {
|
||||
fs.mkdirpSync(fs.dappPath(".embark"));
|
||||
fs.mkdirpSync(utils.dirname(this.socketPath));
|
||||
ipc.serve(this.socketPath, () => {});
|
||||
ipc.server.start();
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
const ProcessState = {
|
||||
Unstarted: 'unstarted',
|
||||
Starting: 'starting',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const async = require('async');
|
||||
const {spawn, exec} = require('child_process');
|
||||
const {exec, spawn} = require('child_process');
|
||||
const fs = require('../../core/fs');
|
||||
const GethMiner = require('./miner');
|
||||
const semver = require('semver');
|
||||
const constants = require('../../constants');
|
||||
|
@ -51,7 +52,7 @@ class GethClient {
|
|||
needKeepAlive() {
|
||||
// TODO: check version also (geth version < 1.8.15)
|
||||
if (this.isDev) {
|
||||
// Trigger regular txs due to a bug in geth (< 1.8.15) and stuck transactions in --dev mode.
|
||||
// Trigger regular txs due to a bug in geth (< 1.8.15) and stuck transactions in --dev mode.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -79,6 +80,8 @@ class GethClient {
|
|||
cmd.push("--verbosity=" + config.verbosity);
|
||||
}
|
||||
|
||||
cmd.push(`--ipcpath=${fs.ipcPath('geth.ipc', true)}`);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const async = require('async');
|
||||
const fs = require('../../core/fs');
|
||||
const NetcatClient = require('netcat/client');
|
||||
|
||||
//Constants
|
||||
|
@ -43,14 +44,7 @@ class GethMiner {
|
|||
}
|
||||
}
|
||||
|
||||
const isWin = process.platform === "win32";
|
||||
|
||||
let ipcPath;
|
||||
if (isWin) {
|
||||
ipcPath = '\\\\.\\pipe\\geth.ipc';
|
||||
} else {
|
||||
ipcPath = this.datadir + '/geth.ipc';
|
||||
}
|
||||
const ipcPath = fs.ipcPath('geth.ipc', true);
|
||||
|
||||
this.client = new NetcatClient();
|
||||
this.client.unixSocket(ipcPath)
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
const {execSync} = require("child_process");
|
||||
const {hostname} = require("os");
|
||||
|
||||
const isDocker = (() => {
|
||||
let isDockerProcess;
|
||||
|
||||
const hostname = require("os").hostname();
|
||||
const pattern = new RegExp(
|
||||
"[0-9]+\:[a-z_-]+\:\/docker\/" + hostname + "[0-9a-z]+", "i",
|
||||
);
|
||||
|
||||
// assumption: an Embark container is always a Linux Docker container, though
|
||||
// the Docker host may be Linux, macOS, or Windows
|
||||
if (process.platform !== "linux") { return false; }
|
||||
try {
|
||||
isDockerProcess = require("child_process")
|
||||
.execSync(
|
||||
"cat /proc/self/cgroup",
|
||||
{stdio: ["ignore", "pipe", "ignore"]},
|
||||
)
|
||||
.toString().match(pattern) !== null;
|
||||
return (
|
||||
new RegExp(`[0-9]+\:[a-z_-]+\:\/docker\/${hostname()}[0-9a-z]+`, "i")
|
||||
).test(
|
||||
execSync(
|
||||
"cat /proc/self/cgroup",
|
||||
{stdio: ["ignore", "pipe", "ignore"]},
|
||||
).toString(),
|
||||
);
|
||||
} catch (e) {
|
||||
isDockerProcess = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return isDockerProcess;
|
||||
})();
|
||||
|
||||
const defaultHost = isDocker ? "0.0.0.0" : "localhost";
|
||||
|
||||
// when we"re runing in Docker, we can expect (generally, in a development
|
||||
// when we're runing in Docker, we can expect (generally, in a development
|
||||
// scenario) that the user would like to connect to the service in the
|
||||
// container via the **host"s** loopback address, so this helper can be used to
|
||||
// container via the **host's** loopback address, so this helper can be used to
|
||||
// swap 0.0.0.0 for localhost in code/messages that pertain to client-side
|
||||
function canonicalHost(host: string): string {
|
||||
return isDocker && host === "0.0.0.0" ? "localhost" : host;
|
||||
|
|
|
@ -390,6 +390,15 @@ function sha3(arg) {
|
|||
return Web3.utils.sha3(arg);
|
||||
}
|
||||
|
||||
function sha512(arg) {
|
||||
if (typeof arg !== 'string') {
|
||||
throw new TypeError('argument must be a string');
|
||||
}
|
||||
const crypto = require('crypto');
|
||||
const hash = crypto.createHash('sha512');
|
||||
return hash.update(arg).digest('hex');
|
||||
}
|
||||
|
||||
function soliditySha3(arg) {
|
||||
const Web3 = require('web3');
|
||||
return Web3.utils.soliditySha3(arg);
|
||||
|
@ -640,6 +649,7 @@ module.exports = {
|
|||
getExternalContractUrl,
|
||||
toChecksumAddress,
|
||||
sha3,
|
||||
sha512,
|
||||
soliditySha3,
|
||||
normalizeInput,
|
||||
buildUrl,
|
||||
|
|
|
@ -31,6 +31,7 @@ describe('fs', () => {
|
|||
'dappPath',
|
||||
'diagramPath',
|
||||
'embarkPath',
|
||||
'ipcPath',
|
||||
'pkgPath',
|
||||
'tmpDir'
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue