Skip to content

Commit 9be3791

Browse files
committed
SCHED-1041: Replace the GPU propagation lock with a settle-window recheck because bind mounts can be reaped seconds after a passing check.
1 parent fb04f50 commit 9be3791

1 file changed

Lines changed: 28 additions & 22 deletions

File tree

images/common/scripts/complement_jail.sh

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ ensure_nvml_soname() {
7171
if [ "${how}" = "lock-busy" ] && [ ! -s "${so1}" ]; then
7272
# The lock holder is still running ldconfig; instead of polling with a guessed delay,
7373
# wait for the lock to be released — that happens exactly when the holder's ldconfig exits
74-
flock --wait 300 etc/complement_jail_ldconfig.lock -c true || echo "[nvml] timed out waiting for the ldconfig lock holder"
74+
flock --wait 60 etc/complement_jail_ldconfig.lock -c true || echo "[nvml] timed out waiting for the ldconfig lock holder"
7575
fi
7676
if [ ! -s "${so1}" ]; then
7777
# Grace re-checks: if the symlink becomes usable here, it was created and only this view lagged
@@ -90,7 +90,7 @@ ensure_nvml_soname() {
9090
# produces correct symlinks no matter what the previous runner saw
9191
echo "[nvml] ANOMALY: libnvidia-ml.so.1 missing or empty after ldconfig phase (${how}), running ldconfig here (SCHED-1041)"
9292
dump_nvml_state "before repair ldconfig (${how})"
93-
flock --wait 300 etc/complement_jail_ldconfig.lock -c "chroot \"${jaildir}\" /usr/sbin/ldconfig" || echo "[nvml] repair ldconfig failed with exit code $?"
93+
flock --wait 60 etc/complement_jail_ldconfig.lock -c "chroot \"${jaildir}\" /usr/sbin/ldconfig" || echo "[nvml] repair ldconfig failed with exit code $?"
9494
if [ ! -s "${so1}" ]; then
9595
echo "[nvml] libnvidia-ml.so.1 still missing or empty after repair, exiting so the container restarts (SCHED-1041)"
9696
dump_nvml_state "final state before exit (${how})"
@@ -122,10 +122,14 @@ gpu_libs_mounted() {
122122
# Run nvidia-container-cli and make sure its bind mounts survived; re-run when the shared-FS
123123
# race detached them (a re-run is safe: mounts stack, existing files are not modified), and
124124
# restart the container if the mounts keep disappearing (SCHED-1041).
125+
# A check passing right after the CLI is not enough: in the observed reproductions the mounts
126+
# were reaped ~2s later, when a neighbor worker touched the still-fresh files on the shared
127+
# jail. So a pass only counts if it survives a short settle window; the jittered sleeps also
128+
# spread the workers apart so retries do not keep colliding.
125129
# Uses cap_args/FAKE_LDCONFIG set by the GPU section. Must be called with CWD = ${jaildir}.
126130
mount_gpu_libs() {
127-
local attempt
128-
for attempt in 1 2 3; do
131+
local attempt backoff
132+
for attempt in 1 2 3 4; do
129133
nvidia-container-cli \
130134
--user \
131135
--debug=/dev/stderr \
@@ -137,14 +141,23 @@ mount_gpu_libs() {
137141
"${cap_args[@]}" \
138142
"${jaildir}"
139143
if gpu_libs_mounted; then
140-
echo "[nvml] GPU libs mounted (attempt ${attempt})"
141-
return 0
144+
sleep $((2 + RANDOM % 3))
145+
if gpu_libs_mounted; then
146+
echo "[nvml] GPU libs mounted and stable (attempt ${attempt})"
147+
return 0
148+
fi
149+
echo "[nvml] ANOMALY: nvidia bind mounts reaped during the settle window, re-running (attempt ${attempt}) (SCHED-1041)"
150+
else
151+
echo "[nvml] ANOMALY: nvidia bind mounts lost right after nvidia-container-cli, re-running (attempt ${attempt}) (SCHED-1041)"
142152
fi
143-
echo "[nvml] ANOMALY: nvidia bind mounts lost right after nvidia-container-cli, re-running (attempt ${attempt}) (SCHED-1041)"
144153
dump_nvml_state "after lost mounts, attempt ${attempt}"
145-
sleep 2
154+
if [ "${attempt}" -lt 4 ]; then
155+
# Exponential backoff with jitter: 2-4s, 4-8s, 8-16s
156+
backoff=$((2 ** attempt))
157+
sleep $((backoff + RANDOM % (backoff + 1)))
158+
fi
146159
done
147-
echo "[nvml] nvidia bind mounts still broken after 3 attempts, exiting so the container restarts (SCHED-1041)"
160+
echo "[nvml] nvidia bind mounts still broken after 4 attempts, exiting so the container restarts (SCHED-1041)"
148161
exit 1
149162
}
150163

@@ -230,21 +243,14 @@ pushd "${jaildir}"
230243

231244
echo "[nvml] Jail mount: $(findmnt --target . --output SOURCE,FSTYPE,OPTIONS --noheadings 2>&1)"
232245

233-
# SCHED-1041: concurrent creation of the driver-lib files on the shared jail makes the kernel silently drop
234-
# the earlier worker's bind mounts (remote dentry invalidation on virtiofs),
235-
# leaving 0-byte placeholders behind the soname symlinks.
236-
# Serialize the propagation across all workers of the cluster: one run takes well under a second, so even
237-
# hundreds of workers pass this lock within minutes, and only cold bring-up pays (later runs find the lock free).
238-
# The kernel releases the lock automatically if we exit while holding it.
239-
exec {gpu_lock_fd}> "etc/complement_jail_gpu_propagate.lock"
240-
if ! flock --wait 1800 "${gpu_lock_fd}"; then
241-
echo "[nvml] timed out waiting for the GPU propagation lock, exiting so the container restarts"
242-
exit 1
243-
fi
246+
# SCHED-1041: when another worker touches the freshly created driver-lib files on the
247+
# shared jail within seconds of their creation, the kernel silently drops this worker's
248+
# bind mounts (remote dentry invalidation on virtiofs), leaving 0-byte placeholders
249+
# behind the soname symlinks. mount_gpu_libs retries until the mounts survive a settle
250+
# window; once the files are more than a few seconds old they are stable (established
251+
# clusters never hit this).
244252
mount_gpu_libs
245253
touch "etc/gpu_libs_installed.flag"
246-
flock --unlock "${gpu_lock_fd}"
247-
exec {gpu_lock_fd}>&-
248254

249255
echo "[nvml] /lib symlink: $(readlink lib 2>/dev/null || echo 'NOT a symlink')"
250256
dump_nvml_state "after nvidia-container-cli"

0 commit comments

Comments
 (0)