diff --git a/bin/flutter b/bin/flutter index 587711b2c0..4fe4802de3 100755 --- a/bin/flutter +++ b/bin/flutter @@ -34,9 +34,41 @@ function path_uri() { } function upgrade_flutter () { + # This function is executed with a redirect that pipes the source of + # this script into file descriptor 3. + # + # To ensure that we don't simultaneously update Dart in multiple + # parallel instances, we try to obtain an exclusive lock on this + # file descriptor (and thus this script's source file) while we are + # updating Dart and compiling the script. To do this, we try to use + # the command line program "flock", which is available on many + # Unix-like platforms, in particular on most Linux distributions. + # You give it a file descriptor, and it locks the corresponding + # 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. + # + # 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 second complication is NFS. On NFS, to obtain an exclusive + # lock you need a file descriptor that is open for writing, because + # NFS implements exclusive locks by writing, or some such. Thus, we + # ignore errors from flock. We do so by using the '|| true' trick, + # since we are running in a 'set -e' environment wherein all errors + # are fatal, and by redirecting all output to /dev/null, since + # 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. if hash flock 2>/dev/null; then - flock 3 # ensures that we don't simultaneously update Dart in multiple parallel instances - # some platforms (e.g. Mac) don't have flock or any reliable alternative + flock 3 2>/dev/null || true fi local revision=`(cd "$FLUTTER_ROOT"; git rev-parse HEAD)`