Skip to content

Commit 05ade5d

Browse files
danielbodartclaude
andcommitted
Atomic lib replacement in update script to prevent mmap corruption
The update script uses cp -a to overwrite shared ORT libraries while the running capsper process has them mmap'd. On Linux, cp truncates and rewrites the same inode, corrupting the running process's memory-mapped pages. This caused segfaults at garbage addresses (e.g. 0x2a0b40 — a corrupted ORT API function pointer) after the daily update timer staged a new release with updated deps. Fix: write .so files to a temp name in the same directory, then mv (rename). The rename is atomic on the same filesystem and creates a new inode, so the running process keeps reading from the old one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0447972 commit 05ade5d

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

dist/linux/capsper-update.sh

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ die() { echo "ERROR: $*" >&2; exit 1; }
1818
cleanup() { [ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"; }
1919
trap cleanup EXIT
2020

21+
# Atomically copy .so files from src_dir to dst_dir.
22+
# Uses cp-to-temp + mv (rename) so the running process keeps
23+
# reading from the old inode — prevents mmap corruption.
24+
atomic_copy_libs() {
25+
local src_dir="$1" dst_dir="$2"
26+
for f in "$src_dir"/*.so "$src_dir"/*.so.*; do
27+
[ -e "$f" ] || continue
28+
local name
29+
name=$(basename "$f")
30+
cp -a "$f" "$dst_dir/$name.tmp"
31+
mv -f "$dst_dir/$name.tmp" "$dst_dir/$name"
32+
done
33+
}
34+
2135
current_version() {
2236
cat "$INSTALL_DIR/current/VERSION" 2>/dev/null || echo "unknown"
2337
}
@@ -72,7 +86,7 @@ ensure_ort_libs() {
7286
if [ -f "$release_dir/lib/libonnxruntime.so" ]; then
7387
echo "Migrating bundled ORT libs to shared directory..."
7488
mkdir -p "$shared_lib"
75-
cp -a "$release_dir/lib/"*.so "$release_dir/lib/"*.so.* "$shared_lib/" 2>/dev/null || true
89+
atomic_copy_libs "$release_dir/lib" "$shared_lib"
7690
[ -n "$needed_version" ] && cp "$release_dir/lib/DEPS_VERSION" "$shared_lib/"
7791
return 0
7892
fi
@@ -110,7 +124,13 @@ ensure_ort_libs() {
110124

111125
mkdir -p "$shared_lib" "$TMP_DIR/deps"
112126
tar -xzf "$TMP_DIR/$DEPS_ASSET" -C "$TMP_DIR/deps"
113-
cp -a "$TMP_DIR/deps/lib/"* "$shared_lib/"
127+
atomic_copy_libs "$TMP_DIR/deps/lib" "$shared_lib"
128+
# Copy non-.so files (DEPS_VERSION, etc.) normally
129+
for f in "$TMP_DIR/deps/lib/"*; do
130+
case "$f" in *.so|*.so.*) continue ;; esac
131+
[ -e "$f" ] || continue
132+
cp -a "$f" "$shared_lib/"
133+
done
114134
echo "ORT runtime libraries installed."
115135
}
116136

0 commit comments

Comments
 (0)