Repository: bazelbuild/bazel
Issue: Windows: Error: corrupt installation
Labels: type: bug
P1
platform: windows
category: misc > misc
breakage

I noticed this error in many places, my local machine, [Bazel CI](https://ci.bazel.io/blue/organizations/jenkins/bazel-tests/detail/bazel-tests/1606/pipeline), [Tensorflow CI](http://ci.tensorflow.org/job/tf-master-win-bzl/2189/console), 
```
Error: corrupt installation: file 'C:\tmp/_bazel_pcloudy/install/6f94f50e4679b4d40059370500e5cb9c/_embedded_binaries/A-server.jar' modified.  Please remove 'C:\tmp/_bazel_pcloudy/install/6f94f50e4679b4d40059370500e5cb9c' and try again.
```

The interesting part is that, it happens with every old Bazel versions **in the new year**!

The file timestamps are all set to `Jan  1  2027`. 
```
pcloudy@tensorflow-jenkins-win-gpu2-slave MSYS ~/workspace/tensorflow
$ ll /c/tmp/_bazel_pcloudy/install/6f94f50e4679b4d40059370500e5cb9c/_embedded_binaries
total 44894
-rw-r--r-- 1 pcloudy None 45074399 Jan  1  2027 A-server.jar
-rwxr-xr-x 1 pcloudy None   257536 Jan  1  2027 build-runfiles.exe
drwxr-xr-x 1 pcloudy None        0 Oct 19 16:13 embedded_tools
-rw-r--r-- 1 pcloudy None       33 Jan  1  2027 install_base_key
-rw-r--r-- 1 pcloudy None        4 Jan  1  2027 java.version
-rw-r--r-- 1 pcloudy None     3849 Jan  1  2027 jdk.BUILD
-rwxr-xr-x 1 pcloudy None    90112 Jan  1  2027 linux-sandbox.exe
-rwxr-xr-x 1 pcloudy None   257536 Jan  1  2027 process-wrapper.exe
-rwxr-xr-x 1 pcloudy None   272896 Jan  1  2027 windows_jni.dll
-rwxr-xr-x 1 pcloudy None      698 Jan  1  2027 xcode-locator
```

@laszlocsomor Do you have any idea about this? Is there anything wrong with our file invalid mechanism?
FYI @mhlopko 

Issue comments:
We ran into the same problem in all our own windows builder machines. Removing the following two directories fixed the problem: C:\Users\builder\\_bazel_LOCAL\ SERVICE/install/dc4fe1b7fd90df4d3976b7aaa4b41899 and cygwin  /tmp/_bazel_LOCAL\ SERVICE/install/dc4fe1b7fd90df4d3976b7aaa4b41899. But it is not addressing the reason for the failure.

PS, the same failure came back. I had to delete the two directories again. The hash in the paths stayed the same. 
@meteorcloudy : This is Windows only, right? Then it's likely a bug in this class: https://github.com/bazelbuild/bazel/blob/master/src/main/cpp/util/file_windows.cc#L156 . Yesterday was Jan 2, did you see this yesterday too, or only on Jan 1, or with Bazel installations from last year?
I saw it on Jan 2 and also today Jan 3, and yes, with every bazel installations from last year.
Yeah the code looks really suspicious. Let me take a closer look.
@mhlopko To fix the Windows CI build, we'll have to delete the installation directories.
@laszlocsomor Thanks!
One workaround is to delete the install directory (dirname of "A-server.jar" in the error message).
Another workaround is to run `touch -m -t 202801010101 $(find path/to/install/dir -type f)` in MSYS shell.
Another workaround: rename the install directory.
This is the easiest approach. It's useful if deleting fails due to long file names. (Delete those directories from MSYS or using Total Commander.)
I hit this bug in my local Windows 10 machine as well on Jan 3. Some Bazel files have the "01/01/202**8**" timestamp.

Reinstalling Bazel fixes the issue, but new Bazel files still have the timestamp of 01/01/2028. See screenshots.

![capture](https://user-images.githubusercontent.com/13115060/34549727-ec3c18f8-f145-11e7-9c33-78dc37be4d38.JPG)
> Reinstalling Bazel fixes the issue, but new Bazel files still have the timestamp of 01/01/2028. See screenshots.

That is working as intended.

When you install Bazel, Bazel unpacks embedded binaries and sets their timestamp to Jan 1, 10+$current_year. It's 2018 now, so the timestamps are 2028/01/01.
Can this be closed? Please re-open if still an issue.
No, this bug is not yet fixed.
Just ran into this issue here.

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index 537852eb70b310..ee045a3718f510 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -114,16 +114,59 @@ class WindowsFileMtime : public IFileMtime {
   bool SetToDistantFuture(const string& path) override;
 
  private:
+  // 1 year in FILETIME.
+  static const ULARGE_INTEGER kOneYear;
   // 9 years in the future.
   const FILETIME near_future_;
   // 10 years in the future.
   const FILETIME distant_future_;
 
-  static FILETIME GetNow();
-  static FILETIME GetFuture(WORD years);
+  static ULARGE_INTEGER&& OneYearDelay();
+  static const FILETIME GetNow();
+  static const FILETIME GetFuture(WORD years);
   static bool Set(const string& path, const FILETIME& time);
 };
 
+const ULARGE_INTEGER WindowsFileMtime::kOneYear =
+    std::move(WindowsFileMtime::OneYearDelay());
+
+ULARGE_INTEGER&& WindowsFileMtime::OneYearDelay() {
+  SYSTEMTIME now;
+  GetSystemTime(&now);
+  now.wMonth = 1;
+  now.wDayOfWeek = 0;
+  now.wDay = 1;
+  now.wHour = 0;
+  now.wMinute = 0;
+  now.wSecond = 0;
+  now.wMilliseconds = 0;
+
+  FILETIME now_ft;
+  if (!::SystemTimeToFileTime(&now, &now_ft)) {
+    string err = GetLastErrorString();
+    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
+        << "WindowsFileMtime::OneYearDelay: SystemTimeToFileTime 1 failed: "
+        << err;
+  }
+  ULARGE_INTEGER t1;
+  t1.LowPart = now_ft.dwLowDateTime;
+  t1.HighPart = now_ft.dwHighDateTime;
+
+  now.wYear++;
+  if (!::SystemTimeToFileTime(&now, &now_ft)) {
+    string err = GetLastErrorString();
+    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
+        << "WindowsFileMtime::OneYearDelay: SystemTimeToFileTime 2 failed: "
+        << err;
+  }
+  ULARGE_INTEGER t2;
+  t2.LowPart = now_ft.dwLowDateTime;
+  t2.HighPart = now_ft.dwHighDateTime;
+
+  t2.QuadPart -= t1.QuadPart;
+  return std::move(t2);
+}
+
 bool WindowsFileMtime::GetIfInDistantFuture(const string& path, bool* result) {
   if (path.empty()) {
     return false;
@@ -215,36 +258,23 @@ bool WindowsFileMtime::Set(const string& path, const FILETIME& time) {
              /* lpLastWriteTime */ &time) == TRUE;
 }
 
-FILETIME WindowsFileMtime::GetNow() {
-  SYSTEMTIME sys_time;
-  ::GetSystemTime(&sys_time);
-  FILETIME file_time;
-  if (!::SystemTimeToFileTime(&sys_time, &file_time)) {
-    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
-        << "WindowsFileMtime::GetNow: SystemTimeToFileTime failed: "
-        << GetLastErrorString();
-  }
-  return file_time;
-}
-
-FILETIME WindowsFileMtime::GetFuture(WORD years) {
-  SYSTEMTIME future_time;
-  GetSystemTime(&future_time);
-  future_time.wYear += years;
-  future_time.wMonth = 1;
-  future_time.wDayOfWeek = 0;
-  future_time.wDay = 1;
-  future_time.wHour = 0;
-  future_time.wMinute = 0;
-  future_time.wSecond = 0;
-  future_time.wMilliseconds = 0;
-  FILETIME file_time;
-  if (!::SystemTimeToFileTime(&future_time, &file_time)) {
-    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
-        << "WindowsFileMtime::GetFuture: SystemTimeToFileTime failed: "
-        << GetLastErrorString();
-  }
-  return file_time;
+const FILETIME WindowsFileMtime::GetNow() {
+  FILETIME now;
+  GetSystemTimeAsFileTime(&now);
+  return now;
+}
+
+const FILETIME WindowsFileMtime::GetFuture(WORD years) {
+  FILETIME result;
+  GetSystemTimeAsFileTime(&result);
+
+  ULARGE_INTEGER result_value;
+  result_value.LowPart = result.dwLowDateTime;
+  result_value.HighPart = result.dwHighDateTime;
+  result_value.QuadPart += kOneYear.QuadPart * years;
+  result.dwLowDateTime = result_value.LowPart;
+  result.dwHighDateTime = result_value.HighPart;
+  return result;
 }
 
 IFileMtime* CreateFileMtime() { return new WindowsFileMtime(); }


Test patch: