@@ -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}.
126130mount_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