Commit 7c2e05b4 authored by Dan Jacques's avatar Dan Jacques Committed by Commit Bot

[cipd] Fix CIPD bootstraps run concurrently.

It's currently possible for CIPD bootstraps that provision concurrently to:
1) On Linux, step on each other during download, and
2) On Windows, fail.

Fix these respective scripts so that bootstraps are safe to use
concurrently.

On Linux and Mac, we download to a temporary file and use "mv" (atomic)
to write it to the final destination. Concurrent initializations will
perform parallel downloads, execute the "mv", and copy their downloaded
file to the destination path.

On Windows, we use filesystem locking to lock the operation and ensure
that only one download can happen.

BUG=chromium:739195
TEST=local
  - Ran in parallel on Windows, Linux, and Max.

Change-Id: Ie050d37598da67389f21728e781bd58904ef9c17
Reviewed-on: https://chromium-review.googlesource.com/560521Reviewed-by: 's avatarRobbie Iannucci <iannucci@chromium.org>
Commit-Queue: Daniel Jacques <dnj@chromium.org>
parent aaf93f48
......@@ -52,8 +52,20 @@ if [ ! -e "$CLIENT" ]; then
echo "Bootstrapping cipd client for ${PLAT}-${ARCH}..."
echo "From $URL"
if hash curl 2> /dev/null ; then
curl "$URL" -f -A "$USER_AGENT" -L -o "$CLIENT"
chmod +x "$CLIENT"
# Download the client into a temporary file, then move it into the final
# location atomically.
#
# This wonky tempdir method works on Linux and Mac.
CIPD_CLIENT_TMP=$(\
mktemp -p "$MYPATH" 2>/dev/null || \
mktemp "$MYPATH/.cipd_client.XXXXXXX")
curl "$URL" -f -A "$USER_AGENT" -L -o "$CIPD_CLIENT_TMP"
chmod +x "$CIPD_CLIENT_TMP"
set +e
mv "$CIPD_CLIENT_TMP" "$CLIENT"
set -e
else
echo Your platform is missing the \`curl\` command. Please use your package
echo manager to install it before continuing.
......
......@@ -40,15 +40,34 @@ try {
}
$Env:CIPD_HTTP_USER_AGENT_PREFIX = $user_agent
if (!(Test-Path $client)) {
echo "Bootstrapping cipd client for $plat-$arch..."
echo "From $url"
# TODO(iannucci): It would be really nice if there was a way to get this to
# show progress without also completely destroying the download speed, but
# I can't seem to find a way to do it. Patches welcome :)
$wc = (New-Object System.Net.WebClient)
$wc.Headers.add('User-Agent', $user_agent)
$wc.DownloadFile($url, $client)
# Use a lock fle to prevent simultaneous processes from stepping on each other.
$cipd_lock = Join-Path $myPath -ChildPath '.cipd_client.lock'
while ($true) {
$cipd_lock_file = $false
try {
$cipd_lock_file = [IO.File]::OpenWrite($cipd_lock)
if (!(Test-Path $client)) {
echo "Bootstrapping cipd client for $plat-$arch..."
echo "From $url"
# TODO(iannucci): It would be really nice if there was a way to get this to
# show progress without also completely destroying the download speed, but
# I can't seem to find a way to do it. Patches welcome :)
$wc = (New-Object System.Net.WebClient)
$wc.Headers.add('User-Agent', $user_agent)
$wc.DownloadFile($url, $client)
}
break
} catch {
echo "CIPD lock is held, trying again after delay..."
Start-Sleep -s 1
} finally {
if ($cipd_lock_file) {
$cipd_lock_file.close()
}
}
}
$_ = & $client selfupdate -version "$cipdClientVer"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment