Skip to content

Commit 51f750f

Browse files
committed
fix: avoid ln race condition in bootstrap script
Avoid startup failures when multiple processes attempt to create the same symlinks simultaneously. Ensure symlinks are created and ignore errors if they already exist, which can happen in a race condition during startup.
1 parent a9de4d5 commit 51f750f

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

python/private/stage1_bootstrap_template.sh

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ if [[ -n "${RULES_PYTHON_BOOTSTRAP_VERBOSE:-}" ]]; then
66
set -x
77
fi
88

9+
# Creates a symlink. If the symlink already exists, it is tolerated to avoid
10+
# race conditions during startup.
11+
function _symlink() {
12+
local target="$1"
13+
local link="$2"
14+
if ln -s "$target" "$link" 2>/dev/null; then
15+
return 0
16+
fi
17+
# If it failed, maybe it already exists because of a race.
18+
if [[ -L "$link" || -e "$link" ]]; then
19+
return 0
20+
fi
21+
# If it doesn't exist, maybe we don't have write permission in the directory.
22+
local dir
23+
dir=$(dirname "$link")
24+
if [[ ! -w "$dir" ]]; then
25+
echo >&2 "ERROR: Cannot create symlink $link: Directory $dir is not writable"
26+
else
27+
echo >&2 "ERROR: Failed to create symlink $link -> $target"
28+
fi
29+
return 1
30+
}
31+
32+
933
# runfiles-root-relative path
1034
STAGE2_BOOTSTRAP="%stage2_bootstrap%"
1135

@@ -153,7 +177,7 @@ if [[ "$IS_ZIPFILE" == "1" ]]; then
153177
fi
154178
# The bin/ directory may not exist if it is empty.
155179
mkdir -p "$(dirname $python_exe)"
156-
ln -s "$symlink_to" "$python_exe"
180+
_symlink "$symlink_to" "$python_exe"
157181
elif [[ "$RECREATE_VENV_AT_RUNTIME" == "1" ]]; then
158182
if [[ -n "$RULES_PYTHON_EXTRACT_ROOT" ]]; then
159183
use_exec=1
@@ -226,16 +250,16 @@ EOF
226250
fi
227251

228252
mkdir -p "$venv/bin"
229-
ln -s "$python_exe_actual" "$python_exe"
253+
_symlink "$python_exe_actual" "$python_exe"
230254

231255
if [[ ! -e "$venv_site_packages" ]]; then
232256
mkdir -p $(dirname $venv_site_packages)
233-
ln -s "$runfiles_venv_site_packages" "$venv_site_packages"
257+
_symlink "$runfiles_venv_site_packages" "$venv_site_packages"
234258
fi
235259
fi
236260

237261
if [[ ! -e "$venv/pyvenv.cfg" ]]; then
238-
ln -s "$runfiles_venv/pyvenv.cfg" "$venv/pyvenv.cfg"
262+
_symlink "$runfiles_venv/pyvenv.cfg" "$venv/pyvenv.cfg"
239263
fi
240264
else
241265
use_exec=1

0 commit comments

Comments
 (0)