Commit 0da9cc9
authored
fix(upgrade): replace Bun.mmap with arrayBuffer on all platforms (#343)
## Problem
Delta upgrades silently fall back to full binary download on **Linux**
because `Bun.mmap()` throws `ETXTBSY` when targeting the running
executable.
`Bun.mmap()` always opens files with `O_RDWR` internally, regardless of
the `shared` flag. When the target file is the currently-running binary:
- **macOS**: AMFI sends uncatchable SIGKILL (writable mapping on signed
Mach-O) — fixed in PR #339/#340
- **Linux**: `open()` returns `ETXTBSY` (kernel blocks opening running
executables for write) — **not fixed until now**
PR #340 added a platform-conditional (`darwin` → `arrayBuffer`, else →
`mmap`) but this was insufficient since mmap fails on **both**
platforms.
### Evidence
```bash
# mmap always fails on the running binary — even with MAP_PRIVATE
$ bun -e 'Bun.mmap(process.execPath, { shared: false })'
ETXTBSY: text file is busy, open
# arrayBuffer works fine (opens with O_RDONLY)
$ bun -e 'await Bun.file(process.execPath).arrayBuffer()'
# ✓ reads ~100MB successfully
```
Confirmed via end-to-end test: chain resolution works perfectly (8 patch
tags, 1-step chain, 19KB patch, SHA-256 matches), but `applyPatch()`
fails on the `Bun.mmap()` call, error is caught by
`attemptDeltaUpgrade()`'s catch-all, and logged at debug level
(invisible without `--verbose`).
## Fix
- Remove platform-conditional in `bspatch.ts`, use `new Uint8Array(await
Bun.file(oldPath).arrayBuffer())` unconditionally on all platforms
- Include error message in delta upgrade debug log so `--verbose`
reveals root cause
- Update JSDoc to reflect the arrayBuffer-only approach
The ~100 MB heap cost is acceptable — it's freed immediately after
patching completes, and the alternative (full ~32 MB gzipped download)
is much slower.
### Performance comparison
| Method | Download size | Total time |
|--------|-------------|------------|
| Full download | ~32 MB .gz | ~7.2s |
| Delta patch | ~19 KB | ~0.85s |1 parent 3cabb9b commit 0da9cc9
3 files changed
+22
-21
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
666 | 666 | | |
667 | 667 | | |
668 | 668 | | |
669 | | - | |
| 669 | + | |
670 | 670 | | |
671 | 671 | | |
672 | 672 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
14 | 17 | | |
15 | 18 | | |
16 | 19 | | |
| |||
210 | 213 | | |
211 | 214 | | |
212 | 215 | | |
213 | | - | |
214 | | - | |
215 | | - | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
216 | 219 | | |
217 | 220 | | |
218 | 221 | | |
| |||
243 | 246 | | |
244 | 247 | | |
245 | 248 | | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
256 | 255 | | |
257 | 256 | | |
258 | 257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
579 | 579 | | |
580 | 580 | | |
581 | 581 | | |
582 | | - | |
583 | | - | |
584 | | - | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
585 | 587 | | |
586 | 588 | | |
587 | 589 | | |
| |||
671 | 673 | | |
672 | 674 | | |
673 | 675 | | |
674 | | - | |
675 | | - | |
| 676 | + | |
| 677 | + | |
676 | 678 | | |
677 | 679 | | |
678 | 680 | | |
| |||
0 commit comments