From bcdbed962802d29da0cc405473a5a93bf77f17a0 Mon Sep 17 00:00:00 2001 From: jcollins-g Date: Fri, 2 Mar 2018 09:52:14 -0800 Subject: [PATCH] Add upgrade locking for macs (#15038) --- bin/flutter | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/bin/flutter b/bin/flutter index 0dc02d8b94..9458f16771 100755 --- a/bin/flutter +++ b/bin/flutter @@ -33,7 +33,13 @@ function path_uri() { echo "$1" | sed -E -e "s,^/+,/," } +function _rmlock () { + [ -n "$FLUTTER_UPGRADE_LOCK" ] && rm -f "$FLUTTER_UPGRADE_LOCK" +} + function upgrade_flutter () { + mkdir -p "$FLUTTER_ROOT/bin/cache" + # This function is executed with a redirect that pipes the source of # this script into file descriptor 3. # @@ -47,14 +53,14 @@ function upgrade_flutter () { # file, having inherited the file descriptor from the shell. # # Complicating matters, there are two major scenarios where this - # will not work. The first is if the platform doesn't have "flock", - # for example on Mac. There does not appear to be any sort of other - # equivalent, so on platforms that don't have flock, we just don't - # do anything. + # will not work. # - # To determine if we have "flock" available, we abuse the "hash" - # shell built-in to determine if "flock" resolves to anything. If it - # does, we call it, otherwise we forget the whole thing. + # The first is if the platform doesn't have "flock", for example on Mac. + # There is not a direct equivalent, so on platforms that don't have flock, + # we fall back to using a lockfile and spinlock with "shlock". This + # doesn't work as well over NFS as it relies on PIDs. Any platform + # without either of these tools has no locking at all. To determine if we + # have "flock" or "shlock" available, we abuse the "hash" shell built-in. # # The second complication is NFS. On NFS, to obtain an exclusive # lock you need a file descriptor that is open for writing, because @@ -65,16 +71,20 @@ function upgrade_flutter () { # users will typically not care about errors from flock and are # more likely to be confused by them than helped. # - # The lock is released when the file descriptor goes out of scope, - # i.e. when this function returns. + # For "flock", the lock is released when the file descriptor goes out of + # scope, i.e. when this function returns. The lock is released via + # a trap when using "shlock". if hash flock 2>/dev/null; then flock 3 2>/dev/null || true + elif hash shlock 2>/dev/null; then + FLUTTER_UPGRADE_LOCK="$FLUTTER_ROOT/bin/cache/.upgrade_lock" + while ! shlock -f "$FLUTTER_UPGRADE_LOCK" -p $$ ; do sleep .1 ; done + trap _rmlock EXIT fi local revision=`(cd "$FLUTTER_ROOT"; git rev-parse HEAD)` if [ ! -f "$SNAPSHOT_PATH" ] || [ ! -s "$STAMP_PATH" ] || [ `cat "$STAMP_PATH"` != "$revision" ] || [ "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]; then rm -f "$FLUTTER_ROOT/version" - mkdir -p "$FLUTTER_ROOT/bin/cache" touch "$FLUTTER_ROOT/bin/cache/.dartignore" "$FLUTTER_ROOT/bin/internal/update_dart_sdk.sh" @@ -97,6 +107,11 @@ function upgrade_flutter () { "$DART" --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" "$SCRIPT_PATH" echo "$revision" > "$STAMP_PATH" fi + # The exit here is duplicitous since the function is run in a subshell, + # but this serves as documentation that running the function in a + # subshell is required to make sure any lockfile created by shlock + # is cleaned up. + exit $? } PROG_NAME="$(path_uri "$(follow_links "$BASH_SOURCE")")"