@andersbakken/fisk 5.0.11 → 5.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/VM_runtime.js +53 -11
- package/package.json +1 -1
- package/scheduler/fisk-scheduler.js +27 -3
package/builder/VM_runtime.js
CHANGED
|
@@ -3039,6 +3039,16 @@ var fs = libExports;
|
|
|
3039
3039
|
const FISK_PAD_LENGTH = 4096;
|
|
3040
3040
|
const FISK_NAME_PAD = "/fisk-name" + "_".repeat(FISK_PAD_LENGTH - "/fisk-name".length);
|
|
3041
3041
|
const FISK_CDIR_PAD = "/fisk-cdir" + "_".repeat(FISK_PAD_LENGTH - "/fisk-cdir".length);
|
|
3042
|
+
// Flags asking the compiler to record its own argv, mapped to the negation the
|
|
3043
|
+
// same compiler spells it with. -g* forms land in DW_AT_producer, -f* forms in a
|
|
3044
|
+
// .GCC.command.line section; clang uses the command-line names and also accepts
|
|
3045
|
+
// the gcc-switches ones as aliases.
|
|
3046
|
+
const RECORD_FLAG_NEGATIONS = {
|
|
3047
|
+
"-grecord-command-line": "-gno-record-command-line",
|
|
3048
|
+
"-frecord-command-line": "-fno-record-command-line",
|
|
3049
|
+
"-grecord-gcc-switches": "-gno-record-gcc-switches",
|
|
3050
|
+
"-frecord-gcc-switches": "-fno-record-gcc-switches"
|
|
3051
|
+
};
|
|
3042
3052
|
class Compile extends EventEmitter__default["default"] {
|
|
3043
3053
|
constructor(args, argv0, dir, debug, sourceFileName, paddedPaths) {
|
|
3044
3054
|
super();
|
|
@@ -3165,20 +3175,52 @@ class Compile extends EventEmitter__default["default"] {
|
|
|
3165
3175
|
throw new Error("No sourcefile");
|
|
3166
3176
|
}
|
|
3167
3177
|
const sourceFileInDir = path__default["default"].join(dir, sourceFileName || path__default["default"].basename(sourcePath));
|
|
3178
|
+
// Padding only pays off where the client's byte scan can reach the pads,
|
|
3179
|
+
// and it is only *needed* for LLVM bitcode, which DwarfPatcher cannot
|
|
3180
|
+
// load. Everywhere else DwarfPatcher already works, and padding actively
|
|
3181
|
+
// breaks it: it matches on the old /compiles path still being in
|
|
3182
|
+
// .debug_str, so once the pads have replaced it there is nothing for the
|
|
3183
|
+
// fallback to match and the pads stay in the debug info.
|
|
3184
|
+
//
|
|
3185
|
+
// - non-clang: gcc never emits bitcode, and some gcc builds (the nrdp
|
|
3186
|
+
// desktop toolchain, for one) compress .debug_str by default with no
|
|
3187
|
+
// flag asking for it, which the byte scan cannot see into.
|
|
3188
|
+
// - -gz: same problem, explicitly requested. -Wl, forms are link-time
|
|
3189
|
+
// and do not affect the object we hand back, so they do not count.
|
|
3190
|
+
const wantsCompressedDebug = args.some((arg) => {
|
|
3191
|
+
if (arg.startsWith("-Wl,")) {
|
|
3192
|
+
return false;
|
|
3193
|
+
}
|
|
3194
|
+
return (arg.startsWith("-gz") && arg !== "-gz=none") || arg.includes("compress-debug-sections");
|
|
3195
|
+
});
|
|
3196
|
+
if (paddedPaths && (!isClang || wantsCompressedDebug)) {
|
|
3197
|
+
if (debug) {
|
|
3198
|
+
console.log("Not padding paths, leaving them to DwarfPatcher:", "isClang", isClang, "wantsCompressedDebug", wantsCompressedDebug);
|
|
3199
|
+
}
|
|
3200
|
+
paddedPaths = false;
|
|
3201
|
+
}
|
|
3168
3202
|
if (paddedPaths) {
|
|
3169
|
-
// -grecord-command-line
|
|
3170
|
-
//
|
|
3171
|
-
//
|
|
3172
|
-
// the
|
|
3173
|
-
//
|
|
3174
|
-
//
|
|
3175
|
-
//
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3203
|
+
// -grecord-command-line (clang) / -frecord-gcc-switches (gcc) embed
|
|
3204
|
+
// our own argv verbatim into DW_AT_producer or .GCC.command.line,
|
|
3205
|
+
// which would (a) add two PATH_MAX pads to every CU and (b) leave
|
|
3206
|
+
// the builder's /compiles path in there, where the client's byte
|
|
3207
|
+
// scan would hit the embedded pad and NUL-truncate the rest of the
|
|
3208
|
+
// recorded command line. The recorded line would be the builder's
|
|
3209
|
+
// rewritten argv anyway -- not the client's -- so turn it off rather
|
|
3210
|
+
// than record something both wrong and mangled.
|
|
3211
|
+
//
|
|
3212
|
+
// Negate each flag in place instead of dropping it and appending one
|
|
3213
|
+
// fixed negation: whichever compiler accepted the positive spelling
|
|
3214
|
+
// necessarily accepts its own negation, whereas a fixed flag is a
|
|
3215
|
+
// guess about the compiler. That guess is what put
|
|
3216
|
+
// -gno-record-command-line (clang 11+, and gcc spells it
|
|
3217
|
+
// -gno-record-gcc-switches) on gcc command lines.
|
|
3218
|
+
for (let i = 0; i < args.length; ++i) {
|
|
3219
|
+
const negation = RECORD_FLAG_NEGATIONS[args[i]];
|
|
3220
|
+
if (negation) {
|
|
3221
|
+
args[i] = negation;
|
|
3179
3222
|
}
|
|
3180
3223
|
}
|
|
3181
|
-
args.push("-gno-record-command-line");
|
|
3182
3224
|
// The more specific source-file rule must come last: both clang and
|
|
3183
3225
|
// gcc let a later -fdebug-prefix-map win over an earlier one, and
|
|
3184
3226
|
// the directory rule is a prefix of the source-file rule.
|
package/package.json
CHANGED
|
@@ -57998,7 +57998,31 @@ const option = options({
|
|
|
57998
57998
|
const common = common$1(option);
|
|
57999
57999
|
let nextCommandId = 0;
|
|
58000
58000
|
const server = new Server(option, common.Version);
|
|
58001
|
-
|
|
58001
|
+
// 5.0.11 is the first client that asks for padded paths and can patch them out
|
|
58002
|
+
// of LTO bitcode. An older client silently produces objects with the builder's
|
|
58003
|
+
// /compiles paths baked into the debug info -- and because paddedPaths is not
|
|
58004
|
+
// part of the object cache key, those objects are then served to up-to-date
|
|
58005
|
+
// clients too, so one stale client poisons everyone's backtraces.
|
|
58006
|
+
const clientMinimumVersion = "5.0.11";
|
|
58007
|
+
// compareVersions throws on an empty or malformed version rather than returning
|
|
58008
|
+
// an ordering, and npmVersion is "" for any client that sends no
|
|
58009
|
+
// x-fisk-npm-version header. Thrown out of the compile handler that would be a
|
|
58010
|
+
// silent hang: uncaughtException keeps the scheduler up, but the request is
|
|
58011
|
+
// abandoned half-handled, so the client waits for a reply that never comes
|
|
58012
|
+
// instead of being told to update. A version we cannot read is not >= the
|
|
58013
|
+
// minimum, so treat it as too old and reject it properly.
|
|
58014
|
+
function clientTooOld(npmVersion) {
|
|
58015
|
+
if (!npmVersion) {
|
|
58016
|
+
return true;
|
|
58017
|
+
}
|
|
58018
|
+
try {
|
|
58019
|
+
return compareVersions(clientMinimumVersion, npmVersion) >= 1;
|
|
58020
|
+
}
|
|
58021
|
+
catch (err) {
|
|
58022
|
+
console.error(`Unparseable client npm version: "${npmVersion}"`, err);
|
|
58023
|
+
return true;
|
|
58024
|
+
}
|
|
58025
|
+
}
|
|
58002
58026
|
const serverStartTime = Date.now();
|
|
58003
58027
|
// A stalled event loop stops calling accept(), the listen backlog fills and the
|
|
58004
58028
|
// kernel then silently drops SYNs, which clients see as a connect timeout rather
|
|
@@ -58848,7 +58872,7 @@ function requestEnvironment(compile) {
|
|
|
58848
58872
|
return true;
|
|
58849
58873
|
}
|
|
58850
58874
|
server.on("clientVerify", (clientVerify) => {
|
|
58851
|
-
if (
|
|
58875
|
+
if (clientTooOld(clientVerify.npmVersion)) {
|
|
58852
58876
|
clientVerify.send("version_mismatch", { minimum_version: `${clientMinimumVersion}` });
|
|
58853
58877
|
}
|
|
58854
58878
|
else {
|
|
@@ -58859,7 +58883,7 @@ server.on("compile", (compile) => {
|
|
|
58859
58883
|
compile.on("log", (event) => {
|
|
58860
58884
|
addLogFile({ source: "client", ip: compile.ip, contents: event.message });
|
|
58861
58885
|
});
|
|
58862
|
-
if (
|
|
58886
|
+
if (clientTooOld(compile.npmVersion)) {
|
|
58863
58887
|
++jobsFailed;
|
|
58864
58888
|
compile.send("version_mismatch", { minimum_version: `${clientMinimumVersion}` });
|
|
58865
58889
|
return;
|