Open pdcastro opened 5 years ago
I patched balena-cli/node_modules/balena-preload/node_modules/tar-fs/index.js
for debugging, and added these console.log
calls:
console.log(`[preload/tar-fs] onstat() filename="${filename}" stat=${require('util').inspect(stat)}`);
console.log(`
isFile()="${stat.isFile()}"
isDirectory()="${stat.isDirectory()}"
isSymbolicLink()="${stat.isSymbolicLink()}"
isFIFO()="${stat.isFIFO()}"`
);
if (stat.isSocket()) return onnextentry() // tar does not support sockets...
The result was:
[preload/tar-fs] onstat() filename="Dockerfile" stat={ mode: 33188,
size: 361,
blksize: 4096,
blocks: 0,
dev: 0,
gid: 20,
ino: 0,
nlink: 0,
rdev: 0,
uid: 500,
atime: 2019-06-16T13:37:18.530Z,
mtime: 2019-06-16T13:36:44.320Z,
ctime: 2019-06-16T13:36:44.320Z,
birthtime: 2019-06-16T13:36:44.320Z,
atimeMs: 1560692238530,
mtimeMs: 1560692204320,
ctimeMs: 1560692204320,
birthtimeMs: 1560692204320,
isFile: [Function],
isDirectory: [Function],
isSymbolicLink: [Function],
isFIFO: [Function] }
isFile()="true"
isDirectory()="false"
isSymbolicLink()="false"
isFIFO()="false"
TypeError: stat.isSocket is not a function
at onstat (/snapshot/balena-cli/node_modules/balena-preload/node_modules/tar-fs/index.js:114:14)
at /snapshot/balena-cli/node_modules/balena-preload/node_modules/tar-fs/index.js:32:39
at zalgoSafe (pkg/prelude/bootstrap.js:261:10)
at pkg/prelude/bootstrap.js:901:9
at pkg/prelude/bootstrap.js:337:5
at pkg/prelude/bootstrap.js:315:14
at FSReqWrap.wrapper [as oncomplete] (fs.js:658:17)
I have further checked these tar-fs
lines:
var xfs = opts.fs || fs
var statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries, opts.sort)
And found that opts.fs
and opts.dereference
are undefined, meaning it should be using the standard fs.lstat()
function. I tried setting opts.dereference=true
, so it used fs.stat()
instead of fs.lstat()
, and it made no difference (still results in the same TypeError).
So a seemingly standard fs.lstat('Dockerfile')
call returns an object that does not have the isSocket()
function, apparently in violation of the Node.js documented API. But we can't say it's a Node.js bug, because:
~So it's the combination of pkg and Linux that causes it to fail.~ So it's down to pkg (the tool that generates the standalone package). I have also investigated the version of Node.js used by pkg
on Linux. It seems to use pre-selected minor/patch releases for a given major Node release, namely v10.4.1 for Node 10 and v8.11.3 for Node 8. pkg
caches the fetched Node in the homedir:
/root/.pkg-cache/v2.5/fetched-v10.4.1-linux-x64
/root/.pkg-cache/v2.5/fetched-v8.11.3-linux-x64
I am not sure how / whether pkg
modifies those fetched versions of Node, but I have tested with both of those (Node 8 and Node 10) and both equally result in that same TypeError
.
Although I am none the wiser on the root cause of the problem, I have found that the following very simple tar-fs
patch avoids the TypeError
and allows balena preload
to work:
// if (stat.isSocket()) return onnextentry()
if (stat.isSocket && stat.isSocket()) return onnextentry()
Given that neither tar-fs
nor balena-preload
use pkg
but balena-cli
does, a patch fix would perhaps belong to balena-cli
rather than balena-preload
or upstream. I am planning to create a balena-cli
PR with that patch, so we can move on.
Related pkg
pull request: https://github.com/zeit/pkg/pull/720
I was investigating balena-cli issue balena-io/balena-cli/issues/1306 and my preliminary findings suggest that:
balena-cli
v10.16.0 works OK withbalena-preload
v8.1.4balena-cli
v10.17.1 and later (also v11.2.1) fail withbalena-preload
v8.2.0, with the error:Interestingly, I've only reproduced the failure on Linux (Docker image
debian:9.9
), not macOS, so it looks like a system-dependent issue.The offending pull request may be: https://github.com/balena-io/balena-preload/pull/206/files