freebuff 0.1.1 → 0.1.4
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/launcher.js +284 -45
- package/package.json +9 -9
package/launcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { spawn } = require('child_process')
|
|
3
|
+
const { execFileSync, spawn } = require('child_process')
|
|
4
4
|
const crypto = require('crypto')
|
|
5
5
|
const fs = require('fs')
|
|
6
6
|
const http = require('http')
|
|
@@ -146,6 +146,9 @@ function createLauncher(productConfig) {
|
|
|
146
146
|
// Tests only. os.homedir() ignores $HOME under `bun test`, so pointing HOME
|
|
147
147
|
// at a temp dir is not enough to keep a test off the real ~/.config.
|
|
148
148
|
configDir: configDirOverride = null,
|
|
149
|
+
// Tests only: stands in for the OS AVX2 probe (/proc/cpuinfo, sysctl),
|
|
150
|
+
// returning true, false, or null for "could not tell".
|
|
151
|
+
cpuAvx2Probe: cpuAvx2ProbeOverride = null,
|
|
149
152
|
} = productConfig
|
|
150
153
|
|
|
151
154
|
/**
|
|
@@ -257,6 +260,52 @@ function createLauncher(productConfig) {
|
|
|
257
260
|
)
|
|
258
261
|
}
|
|
259
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Bun's own crash report saying this CPU cannot run the optimized build.
|
|
265
|
+
*
|
|
266
|
+
* On Windows the exit code does not carry that. Bun's crash handler catches
|
|
267
|
+
* EXCEPTION_ILLEGAL_INSTRUCTION itself, prints a report, then leaves through
|
|
268
|
+
* Zig's std.posix.abort(), which on Windows is ExitProcess(3). So an AVX2
|
|
269
|
+
* build on a CPU without AVX2 exits with plain code 3, neither
|
|
270
|
+
* 0xC000001D nor 0xC0000409, and both checks above miss it. The Sept 27
|
|
271
|
+
* report (i3-2100, Bun 1.3.14) is exactly this:
|
|
272
|
+
*
|
|
273
|
+
* CPU: sse42 avx
|
|
274
|
+
* Features: no_avx2
|
|
275
|
+
* panic: Illegal instruction at address 0x7FF61902F82C
|
|
276
|
+
* panicked during a panic. Aborting.
|
|
277
|
+
*
|
|
278
|
+
* The report is in the stderr tail watchLaunch() keeps on Windows. Either line
|
|
279
|
+
* is proof, not a guess. `Features: no_avx2` is Bun's own CPUID answer, and a
|
|
280
|
+
* Bun "Illegal instruction" panic is the same Windows exception
|
|
281
|
+
* 0xC000001D reports, intercepted before it became the exit code. Only Bun's
|
|
282
|
+
* exact formats count, so ordinary output that mentions them does not.
|
|
283
|
+
*/
|
|
284
|
+
const BUN_NO_AVX2_FEATURE = /^Features:[^\n]*\bno_avx2\b/m
|
|
285
|
+
const BUN_ILLEGAL_INSTRUCTION_PANIC =
|
|
286
|
+
/^panic(?:\([^)\n]*\))?: Illegal instruction at address 0x[0-9a-f]+/im
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Bun's `CPU:` header line lists the features it detected (`CPU: sse42
|
|
290
|
+
* popcnt avx avx2`). avx2 in that list is Bun's own CPUID saying the CPU has
|
|
291
|
+
* it, so an illegal instruction on such a machine is not a missing AVX2.
|
|
292
|
+
*/
|
|
293
|
+
const BUN_CPU_LINE = /^CPU:([^\n]*)$/m
|
|
294
|
+
|
|
295
|
+
function stderrReportsAvx2Present(stderrTail) {
|
|
296
|
+
if (!stderrTail) return false
|
|
297
|
+
const match = BUN_CPU_LINE.exec(sanitizeForReplay(stderrTail))
|
|
298
|
+
return Boolean(match && /(?:^|\s)avx2(?:\s|$)/i.test(match[1]))
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function stderrReportsMissingCpuFeature(code, signal, stderrTail) {
|
|
302
|
+
if (!stderrTail || (code === 0 && !signal)) return false
|
|
303
|
+
const text = sanitizeForReplay(stderrTail)
|
|
304
|
+
return (
|
|
305
|
+
BUN_NO_AVX2_FEATURE.test(text) || BUN_ILLEGAL_INSTRUCTION_PANIC.test(text)
|
|
306
|
+
)
|
|
307
|
+
}
|
|
308
|
+
|
|
260
309
|
function createConfig(packageName) {
|
|
261
310
|
const homeDir = os.homedir()
|
|
262
311
|
const configDir =
|
|
@@ -409,12 +458,75 @@ function createLauncher(productConfig) {
|
|
|
409
458
|
return null
|
|
410
459
|
}
|
|
411
460
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
461
|
+
/**
|
|
462
|
+
* `/proc/cpuinfo` answers for the kernel's view of the CPU: true or false
|
|
463
|
+
* from its `flags` lines, null when it has none to read.
|
|
464
|
+
*/
|
|
465
|
+
function parseCpuinfoAvx2(text) {
|
|
466
|
+
if (typeof text !== 'string' || !/^flags\s*:/m.test(text)) return null
|
|
467
|
+
return /^flags\s*:.*\bavx2\b/m.test(text)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** `sysctl -n hw.optional.avx2_0` prints 1 or 0 on an Intel Mac. */
|
|
471
|
+
function parseSysctlAvx2(output) {
|
|
472
|
+
const value = typeof output === 'string' ? output.trim() : ''
|
|
473
|
+
if (value === '1') return true
|
|
474
|
+
if (value === '0') return false
|
|
475
|
+
return null
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Where probeCpuAvx2() gets its answer, recorded as the evidence for a pin.
|
|
479
|
+
function cpuProbeSource() {
|
|
480
|
+
if (process.platform === 'linux') return 'cpuinfo'
|
|
481
|
+
if (process.platform === 'darwin') return 'sysctl'
|
|
482
|
+
return 'probe'
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
let _cpuProbeCache
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Ask the OS whether this CPU has AVX2: true, false, or null for "could not
|
|
489
|
+
* tell". Linux reads /proc/cpuinfo. macOS asks sysctl, which costs a
|
|
490
|
+
* subprocess, so this runs only on the crash path, when re-checking an old
|
|
491
|
+
* pin, and when picking a download target for a baseline install, never on
|
|
492
|
+
* an ordinary launch. Windows has no probe: the one we had tripped Defender
|
|
493
|
+
* (see detectMachineHasAvx2), so there Bun's crash report is the evidence.
|
|
494
|
+
*/
|
|
495
|
+
function probeCpuAvx2() {
|
|
496
|
+
if (_cpuProbeCache === undefined) {
|
|
497
|
+
_cpuProbeCache = cpuAvx2ProbeOverride
|
|
498
|
+
? cpuAvx2ProbeOverride()
|
|
499
|
+
: probeCpuAvx2FromOs()
|
|
500
|
+
}
|
|
501
|
+
return _cpuProbeCache
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function probeCpuAvx2FromOs() {
|
|
505
|
+
if (process.arch !== 'x64') return null
|
|
506
|
+
if (process.platform === 'linux') {
|
|
507
|
+
try {
|
|
508
|
+
return parseCpuinfoAvx2(fs.readFileSync('/proc/cpuinfo', 'utf8'))
|
|
509
|
+
} catch {
|
|
510
|
+
return null
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (process.platform === 'darwin') {
|
|
514
|
+
// x64 node on Apple Silicon runs under Rosetta, and sysctl (arm64 only)
|
|
515
|
+
// then describes the host, not what Rosetta emulates. No answer there.
|
|
516
|
+
if (/\bApple\b/.test(os.cpus()[0]?.model || '')) return null
|
|
517
|
+
try {
|
|
518
|
+
return parseSysctlAvx2(
|
|
519
|
+
execFileSync('/usr/sbin/sysctl', ['-n', 'hw.optional.avx2_0'], {
|
|
520
|
+
encoding: 'utf8',
|
|
521
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
522
|
+
timeout: 2000,
|
|
523
|
+
}),
|
|
524
|
+
)
|
|
525
|
+
} catch {
|
|
526
|
+
return null
|
|
527
|
+
}
|
|
417
528
|
}
|
|
529
|
+
return null
|
|
418
530
|
}
|
|
419
531
|
|
|
420
532
|
let _hasAvx2Cache
|
|
@@ -431,17 +543,33 @@ function createLauncher(productConfig) {
|
|
|
431
543
|
return true
|
|
432
544
|
}
|
|
433
545
|
|
|
434
|
-
// A recorded
|
|
435
|
-
//
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
546
|
+
// A recorded verdict outranks everything below it. Every record now names
|
|
547
|
+
// its evidence: Bun's crash report, the OS probe, or 'crash' for an
|
|
548
|
+
// illegal instruction nothing could explain.
|
|
549
|
+
//
|
|
550
|
+
// A record WITHOUT evidence was written by an older launcher, which pinned
|
|
551
|
+
// baseline on any SIGILL, including a bug on a CPU that has AVX2. Re-check
|
|
552
|
+
// those against the OS once: a CPU with AVX2 gets its record dropped and
|
|
553
|
+
// the optimized build back on the next update (see getDownloadTargetKey).
|
|
554
|
+
const record = readCpuFeatureRecord()
|
|
555
|
+
if (record && (record.avx2 || record.evidence)) {
|
|
556
|
+
return record.avx2
|
|
557
|
+
}
|
|
558
|
+
if (record) {
|
|
559
|
+
const probed = probeCpuAvx2()
|
|
560
|
+
if (probed !== true) {
|
|
561
|
+
writeCpuFeatureRecord(
|
|
562
|
+
false,
|
|
563
|
+
probed === false ? cpuProbeSource() : 'crash',
|
|
564
|
+
)
|
|
565
|
+
return false
|
|
566
|
+
}
|
|
567
|
+
clearCpuFeatureRecord()
|
|
440
568
|
}
|
|
441
569
|
|
|
442
570
|
// Linux can just ask, and a file read is cheap enough not to cache.
|
|
443
571
|
if (process.platform === 'linux') {
|
|
444
|
-
return
|
|
572
|
+
return probeCpuAvx2() ?? true
|
|
445
573
|
}
|
|
446
574
|
|
|
447
575
|
// Everything else assumes AVX2 — true of every x64 CPU since ~2013.
|
|
@@ -459,42 +587,77 @@ function createLauncher(productConfig) {
|
|
|
459
587
|
return true
|
|
460
588
|
}
|
|
461
589
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
590
|
+
/**
|
|
591
|
+
* Positive evidence that this CPU runs the optimized build: a recorded
|
|
592
|
+
* verdict with evidence, or the OS probe. The optimistic default does not
|
|
593
|
+
* count. This is what lets a baseline install move back to the optimized
|
|
594
|
+
* build; without evidence, baseline stays put.
|
|
595
|
+
*/
|
|
596
|
+
function knownToHaveAvx2() {
|
|
597
|
+
if (!machineHasAvx2()) return false
|
|
598
|
+
const record = readCpuFeatureRecord()
|
|
599
|
+
if (record?.avx2 === true && record.evidence) return true
|
|
600
|
+
return probeCpuAvx2() === true
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Called from the illegal-instruction fallback, only when the CPU is shown
|
|
604
|
+
// to lack AVX2 or nothing can say either way (see tryFallbackToBaseline).
|
|
605
|
+
// Persisting here is what keeps the optimistic assumption above from costing
|
|
606
|
+
// more than a single crash — and it is deliberately separate from the
|
|
607
|
+
// metadata target, so a lost or rewritten metadata file can't resurrect the
|
|
608
|
+
// AVX2 build on a CPU that can't run it.
|
|
609
|
+
function recordMachineLacksAvx2(evidence = 'crash') {
|
|
467
610
|
_hasAvx2Cache = false
|
|
468
|
-
|
|
611
|
+
writeCpuFeatureRecord(false, evidence)
|
|
469
612
|
}
|
|
470
613
|
|
|
471
614
|
function getCpuFeatureCachePath() {
|
|
472
615
|
return path.join(CONFIG.configDir, 'cpu-features.json')
|
|
473
616
|
}
|
|
474
617
|
|
|
475
|
-
|
|
618
|
+
/** `{ avx2, evidence }`; evidence is null on a record from an older launcher. */
|
|
619
|
+
function readCpuFeatureRecord() {
|
|
476
620
|
try {
|
|
477
621
|
const cache = JSON.parse(
|
|
478
622
|
fs.readFileSync(getCpuFeatureCachePath(), 'utf8'),
|
|
479
623
|
)
|
|
480
|
-
|
|
624
|
+
if (typeof cache.avx2 !== 'boolean') return null
|
|
625
|
+
return {
|
|
626
|
+
avx2: cache.avx2,
|
|
627
|
+
evidence:
|
|
628
|
+
typeof cache.evidence === 'string' && cache.evidence
|
|
629
|
+
? cache.evidence
|
|
630
|
+
: null,
|
|
631
|
+
}
|
|
481
632
|
} catch {
|
|
482
633
|
return null
|
|
483
634
|
}
|
|
484
635
|
}
|
|
485
636
|
|
|
486
|
-
function
|
|
637
|
+
function readCachedAvx2() {
|
|
638
|
+
return readCpuFeatureRecord()?.avx2 ?? null
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function writeCpuFeatureRecord(value, evidence) {
|
|
487
642
|
try {
|
|
488
643
|
fs.mkdirSync(CONFIG.configDir, { recursive: true })
|
|
489
644
|
fs.writeFileSync(
|
|
490
645
|
getCpuFeatureCachePath(),
|
|
491
|
-
JSON.stringify({ avx2: value }),
|
|
646
|
+
JSON.stringify({ avx2: value, evidence }),
|
|
492
647
|
)
|
|
493
648
|
} catch {
|
|
494
649
|
// Best effort; we'll just re-probe next launch.
|
|
495
650
|
}
|
|
496
651
|
}
|
|
497
652
|
|
|
653
|
+
function clearCpuFeatureRecord() {
|
|
654
|
+
try {
|
|
655
|
+
fs.unlinkSync(getCpuFeatureCachePath())
|
|
656
|
+
} catch {
|
|
657
|
+
// Already gone, or unwritable; either way nothing pins baseline now.
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
498
661
|
function getDefaultTargetKey() {
|
|
499
662
|
const override = getTargetOverride()
|
|
500
663
|
if (override) {
|
|
@@ -547,6 +710,17 @@ function createLauncher(productConfig) {
|
|
|
547
710
|
|
|
548
711
|
const metadata = getCurrentMetadata()
|
|
549
712
|
if (metadata?.target && isTargetAllowedForThisMachine(metadata.target)) {
|
|
713
|
+
// An installed baseline keeps running (isTargetAllowedForThisMachine
|
|
714
|
+
// always allows it), but it is not a life sentence: once there is
|
|
715
|
+
// evidence the CPU has AVX2, the next download goes back to the optimized
|
|
716
|
+
// build. That is how a machine sent to baseline by a crash that was not a
|
|
717
|
+
// missing AVX2 re-probes on the next version.
|
|
718
|
+
if (
|
|
719
|
+
metadata.target === getBaselineFallbackTargetKey() &&
|
|
720
|
+
knownToHaveAvx2()
|
|
721
|
+
) {
|
|
722
|
+
return getDefaultTargetKey()
|
|
723
|
+
}
|
|
550
724
|
return metadata.target
|
|
551
725
|
}
|
|
552
726
|
|
|
@@ -1406,7 +1580,9 @@ function createLauncher(productConfig) {
|
|
|
1406
1580
|
const { msAlive = null, stderrTail = '' } = context
|
|
1407
1581
|
// Windows NTSTATUS codes (unsigned DWORD)
|
|
1408
1582
|
const unsignedCode = getUnsignedExitCode(code)
|
|
1409
|
-
const isIllegalInstruction =
|
|
1583
|
+
const isIllegalInstruction =
|
|
1584
|
+
isIllegalInstructionExit(code, signal) ||
|
|
1585
|
+
stderrReportsMissingCpuFeature(code, signal, stderrTail)
|
|
1410
1586
|
const isAccessViolation =
|
|
1411
1587
|
signal === 'SIGSEGV' ||
|
|
1412
1588
|
(process.platform === 'win32' && unsignedCode === 0xc0000005)
|
|
@@ -1429,7 +1605,15 @@ function createLauncher(productConfig) {
|
|
|
1429
1605
|
)
|
|
1430
1606
|
console.error('This typically affects CPUs from before 2013.')
|
|
1431
1607
|
console.error('')
|
|
1432
|
-
|
|
1608
|
+
if (getCurrentMetadata()?.target === getBaselineFallbackTargetKey()) {
|
|
1609
|
+
console.error(
|
|
1610
|
+
'This is already the older-CPU (baseline) build — please include the',
|
|
1611
|
+
)
|
|
1612
|
+
console.error('output below in your report.')
|
|
1613
|
+
console.error('')
|
|
1614
|
+
} else {
|
|
1615
|
+
printBaselineOverrideHint()
|
|
1616
|
+
}
|
|
1433
1617
|
} else if (isAccessViolation) {
|
|
1434
1618
|
console.error('The binary crashed with an access violation.')
|
|
1435
1619
|
console.error('')
|
|
@@ -1664,11 +1848,15 @@ function createLauncher(productConfig) {
|
|
|
1664
1848
|
}
|
|
1665
1849
|
}
|
|
1666
1850
|
|
|
1667
|
-
async function tryFallbackToBaseline(code, signal, msAlive) {
|
|
1668
|
-
//
|
|
1669
|
-
// STATUS_ILLEGAL_INSTRUCTION
|
|
1670
|
-
//
|
|
1671
|
-
|
|
1851
|
+
async function tryFallbackToBaseline(code, signal, msAlive, stderrTail = '') {
|
|
1852
|
+
// Three spellings of one failure, at two levels of certainty. SIGILL /
|
|
1853
|
+
// STATUS_ILLEGAL_INSTRUCTION, or Bun's crash report naming the missing
|
|
1854
|
+
// feature (see stderrReportsMissingCpuFeature), is proof this CPU cannot
|
|
1855
|
+
// run this build; a Windows startup abort is a strong suspicion (see
|
|
1856
|
+
// isStartupCpuFeatureCrash).
|
|
1857
|
+
let confirmed =
|
|
1858
|
+
isIllegalInstructionExit(code, signal) ||
|
|
1859
|
+
stderrReportsMissingCpuFeature(code, signal, stderrTail)
|
|
1672
1860
|
if (!confirmed && !isStartupCpuFeatureCrash(code, signal, msAlive)) {
|
|
1673
1861
|
return false
|
|
1674
1862
|
}
|
|
@@ -1689,16 +1877,35 @@ function createLauncher(productConfig) {
|
|
|
1689
1877
|
return false
|
|
1690
1878
|
}
|
|
1691
1879
|
|
|
1692
|
-
//
|
|
1693
|
-
//
|
|
1694
|
-
//
|
|
1695
|
-
//
|
|
1696
|
-
//
|
|
1697
|
-
//
|
|
1698
|
-
//
|
|
1699
|
-
if
|
|
1700
|
-
|
|
1701
|
-
|
|
1880
|
+
// An illegal instruction proves the binary used an instruction this
|
|
1881
|
+
// machine refused, not that the instruction was AVX2: a Bun or JIT bug
|
|
1882
|
+
// raises SIGILL too. So ask for evidence before pinning baseline, which
|
|
1883
|
+
// otherwise sticks for good.
|
|
1884
|
+
//
|
|
1885
|
+
// - The CPU lacks AVX2 (Bun's `Features: no_avx2`, or the OS probe):
|
|
1886
|
+
// record it. Persisting before the download is what caps the cost at
|
|
1887
|
+
// one crash: even if the download or the relaunch fails, we never
|
|
1888
|
+
// optimistically pick the AVX2 build again.
|
|
1889
|
+
// - The CPU has AVX2 (the OS probe, or avx2 in Bun's `CPU:` line): this
|
|
1890
|
+
// crash is something else. Run baseline for now, since it may still
|
|
1891
|
+
// start, and record the evidence so the next update goes back to the
|
|
1892
|
+
// optimized build (getDownloadTargetKey). At worst one crash per release.
|
|
1893
|
+
// - No evidence either way (Windows without Bun's report, an unreadable
|
|
1894
|
+
// /proc/cpuinfo, Rosetta): a confirmed crash is pinned as before.
|
|
1895
|
+
// A suspected crash records nothing: installing the baseline already keeps
|
|
1896
|
+
// this machine on it, and cpu-features.json should not assert a CPU
|
|
1897
|
+
// limitation we never observed.
|
|
1898
|
+
const verdict = crashAvx2Verdict(code, signal, stderrTail)
|
|
1899
|
+
if (verdict.avx2 === true) {
|
|
1900
|
+
writeCpuFeatureRecord(true, verdict.evidence)
|
|
1901
|
+
confirmed = false
|
|
1902
|
+
} else if (verdict.avx2 === false) {
|
|
1903
|
+
recordMachineLacksAvx2(verdict.evidence)
|
|
1904
|
+
confirmed = true
|
|
1905
|
+
} else if (confirmed) {
|
|
1906
|
+
recordMachineLacksAvx2('crash')
|
|
1907
|
+
}
|
|
1908
|
+
const cpuHasAvx2 = verdict.avx2 === true
|
|
1702
1909
|
|
|
1703
1910
|
let version = metadata?.version || null
|
|
1704
1911
|
let binaryChecksums = null
|
|
@@ -1716,9 +1923,11 @@ function createLauncher(productConfig) {
|
|
|
1716
1923
|
})
|
|
1717
1924
|
console.error('')
|
|
1718
1925
|
console.error(
|
|
1719
|
-
|
|
1720
|
-
? `${packageName}
|
|
1721
|
-
:
|
|
1926
|
+
cpuHasAvx2
|
|
1927
|
+
? `${packageName} crashed, but this CPU supports AVX2; using the older-CPU binary until the next update.`
|
|
1928
|
+
: confirmed
|
|
1929
|
+
? `${packageName} is switching to the older-CPU binary for this machine.`
|
|
1930
|
+
: `${packageName} crashed on startup; trying the older-CPU binary.`,
|
|
1722
1931
|
)
|
|
1723
1932
|
|
|
1724
1933
|
try {
|
|
@@ -1734,6 +1943,27 @@ function createLauncher(productConfig) {
|
|
|
1734
1943
|
return true
|
|
1735
1944
|
}
|
|
1736
1945
|
|
|
1946
|
+
/**
|
|
1947
|
+
* What the evidence says about AVX2 after a crash: `{ avx2, evidence }`,
|
|
1948
|
+
* avx2 null when nothing can tell. Bun's own verdict that AVX2 is missing
|
|
1949
|
+
* wins, then the OS probe, then avx2 in Bun's `CPU:` line.
|
|
1950
|
+
*/
|
|
1951
|
+
function crashAvx2Verdict(code, signal, stderrTail) {
|
|
1952
|
+
if (
|
|
1953
|
+
stderrTail &&
|
|
1954
|
+
!(code === 0 && !signal) &&
|
|
1955
|
+
BUN_NO_AVX2_FEATURE.test(sanitizeForReplay(stderrTail))
|
|
1956
|
+
) {
|
|
1957
|
+
return { avx2: false, evidence: 'bun-report' }
|
|
1958
|
+
}
|
|
1959
|
+
const probed = probeCpuAvx2()
|
|
1960
|
+
if (probed !== null) return { avx2: probed, evidence: cpuProbeSource() }
|
|
1961
|
+
if (stderrReportsAvx2Present(stderrTail)) {
|
|
1962
|
+
return { avx2: true, evidence: 'bun-report' }
|
|
1963
|
+
}
|
|
1964
|
+
return { avx2: null, evidence: null }
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1737
1967
|
function attachExitHandler(child, allowBaselineFallback = true) {
|
|
1738
1968
|
const exitListener = async (code, signal) => {
|
|
1739
1969
|
// A child we never watched (only reachable from a test) reports no age
|
|
@@ -1741,15 +1971,18 @@ function createLauncher(productConfig) {
|
|
|
1741
1971
|
// as a startup crash and trigger a download.
|
|
1742
1972
|
const msAlive = child.launch ? child.launch.msAlive() : Infinity
|
|
1743
1973
|
|
|
1974
|
+
// Any failed exit, not only a native crash code: a Bun crash on Windows
|
|
1975
|
+
// usually exits with plain code 3, and the reason is only in its stderr
|
|
1976
|
+
// (see stderrReportsMissingCpuFeature). Clean exits skip the wait.
|
|
1744
1977
|
let stderrTail = ''
|
|
1745
|
-
if (child.launch && (
|
|
1978
|
+
if (child.launch && (code !== 0 || signal)) {
|
|
1746
1979
|
await child.launch.drained()
|
|
1747
1980
|
stderrTail = child.launch.stderrTail()
|
|
1748
1981
|
}
|
|
1749
1982
|
|
|
1750
1983
|
if (
|
|
1751
1984
|
allowBaselineFallback &&
|
|
1752
|
-
(await tryFallbackToBaseline(code, signal, msAlive))
|
|
1985
|
+
(await tryFallbackToBaseline(code, signal, msAlive, stderrTail))
|
|
1753
1986
|
) {
|
|
1754
1987
|
return
|
|
1755
1988
|
}
|
|
@@ -1793,8 +2026,14 @@ function createLauncher(productConfig) {
|
|
|
1793
2026
|
detectMachineHasAvx2,
|
|
1794
2027
|
recordMachineLacksAvx2,
|
|
1795
2028
|
readCachedAvx2,
|
|
2029
|
+
readCpuFeatureRecord,
|
|
2030
|
+
parseCpuinfoAvx2,
|
|
2031
|
+
parseSysctlAvx2,
|
|
2032
|
+
stderrReportsAvx2Present,
|
|
2033
|
+
getDownloadTargetKey,
|
|
1796
2034
|
isIllegalInstructionExit,
|
|
1797
2035
|
isStartupCpuFeatureCrash,
|
|
2036
|
+
stderrReportsMissingCpuFeature,
|
|
1798
2037
|
tryFallbackToBaseline,
|
|
1799
2038
|
printCrashDiagnostics,
|
|
1800
2039
|
checkForUpdates,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freebuff",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "The world's strongest free coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"provenance": false
|
|
42
42
|
},
|
|
43
43
|
"binaryChecksums": {
|
|
44
|
-
"linux-x64": "
|
|
45
|
-
"linux-x64-baseline": "
|
|
46
|
-
"linux-arm64": "
|
|
47
|
-
"darwin-x64": "
|
|
48
|
-
"darwin-x64-baseline": "
|
|
49
|
-
"darwin-arm64": "
|
|
50
|
-
"win32-x64": "
|
|
51
|
-
"win32-x64-baseline": "
|
|
44
|
+
"linux-x64": "02645c1354b0f72ae3ae6c138fd34b2f74afdf4552f17008713ff2f00f4af1ef",
|
|
45
|
+
"linux-x64-baseline": "5b758c46c3fb289fbd8ae04ce42c304a91e87a20ff5eab338e17cbc03e937831",
|
|
46
|
+
"linux-arm64": "9f40b2b4d76cacaa1f0d598cdfe3a5534e8f3e787803c604319dee569e08d923",
|
|
47
|
+
"darwin-x64": "ef2e71cd81b3166d6449e04221cc547a499bef90ba07c5087783650f63c72854",
|
|
48
|
+
"darwin-x64-baseline": "0d860e9b5cfb178f989fc5c23695d1c5f2328175683f2046775d59df77259f9c",
|
|
49
|
+
"darwin-arm64": "5c40f26c55f11b3395eae3d509ebbed9ffceaf1b06b929cfc90a4860cf64ac35",
|
|
50
|
+
"win32-x64": "826dd49fd9b412aaa87f023901a16872813832b84cda0bad0d97f14eb5ab63eb",
|
|
51
|
+
"win32-x64-baseline": "588cd19c2cdbfd9d323e1b1b737ae9e802404231293a2208a66494fc8ea93e5a"
|
|
52
52
|
}
|
|
53
53
|
}
|