Skip to content

Commit

Permalink
Fix race when extracting the install base when Bazel runs in a PID na…
Browse files Browse the repository at this point in the history
…mespace.

The PID is not a unique identifier in that case and if multiple instances of Bazel tried to extract itself to a shared location at the same time, they occasionally corrupted their temporary extraction directories. This is sometimes the case on CI systems (most notably Bazel's own CI), because a shared install base reduces the overhead of running the integration test suite a lot, as otherwise every test will extract its individual copy of Bazel.

RELNOTES: None.
PiperOrigin-RevId: 291685865
  • Loading branch information
philwo authored and copybara-github committed Jan 27, 2020
1 parent 121933e commit bdf34d7
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/main/cpp/blaze.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
#include <utility>
#include <vector>

#if !defined(_WIN32)
#include <sys/stat.h>
#include <unistd.h>
#endif

#include "src/main/cpp/archive_utils.h"
#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/blaze_util_platform.h"
Expand Down Expand Up @@ -955,7 +960,29 @@ static DurationMillis ExtractData(const string &self_path,
if (!blaze_util::PathExists(install_base)) {
uint64_t st = GetMillisecondsMonotonic();
// Work in a temp dir to avoid races.
#if defined(_WIN32)
string tmp_install = install_base + ".tmp." + blaze::GetProcessIdAsString();
#else
// On Linux, we can't use the PID as a unique identifier, because Bazel
// might run in a PID namespace and then all Bazel clients have the same
// PID, so we use mkdtemp instead.
std::vector<char> tmp_path(install_base.size() + strlen(".tmp.XXXXXX") + 1);
strcpy(tmp_path.data(), install_base.c_str());
strcat(tmp_path.data(), ".tmp.XXXXXX");
if (!blaze_util::MakeDirectories(blaze_util::Dirname(install_base), 0777)) {
BAZEL_DIE(blaze_exit_code::INTERNAL_ERROR)
<< "couldn't create '" << blaze_util::Dirname(install_base)
<< "': " << blaze_util::GetLastErrorString();
}
if (mkdtemp(tmp_path.data()) == nullptr) {
char *err = strerror(errno);
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "could not create temporary directory to extract install base"
<< " (" << err << ")";
}
string tmp_install = tmp_path.data();
chmod(tmp_install.c_str(), 0777);
#endif
ExtractArchiveOrDie(self_path, startup_options.product_name,
expected_install_md5, tmp_install);
BlessFiles(tmp_install);
Expand Down

0 comments on commit bdf34d7

Please sign in to comment.