Thursday, 25 July 2013

Using Hard Links in your builds

Our build engine performs as much work as possible concurrently, to reduce feedback times as much as possible.

But sometimes, it feels like MSBuild wasn't really deigned for this type of activity. We'd previously had issues with locked files which we'd managed to resolve, but even with no over-lapping project compilations, we were still hitting a locked file during copy operations from time to time.

We would see an MSB3021 sporadically, in different branches, on different computers. Ther was no pattern of behaviour would could discern.

Symptoms

MSBuild will complain that it couldn't copy a file because it was locked.
It is normally, an assembly being copied into BIN

E.g. "The process cannot access the file ______.___ because it is being used by another process. msbuild"

Also, the problem can manifest within Windows Explorer:
  • The file can not be deleted
  • You can not take ownership of the file
The only cure, appears to be rebooting the PC, then the file is gone. 

The cause

Absolutely no idea, it seems to strike randomly, and without reason.

The fix

In our case, we made three modifications, based upon other peoples experiences.

1) Enabled the "Application Experience" service.

2) Allowed MSBuild to use Hard Links (aka. Symbolic Links) 
The Hard Link effectively creates an alias to the original file, and doesn't attempt to copy it.
  • /p:UseHardlinksIfPossible=true
  • /p:CreateHardLinksForCopyFilesToOutputDirectoryIfPossible=true
  • /p:CreateHardLinksForCopyAdditionalFilesIfPossible=true
  • /p:CreateHardLinksForCopyLocalIfPossible=true
  • /p:CreateHardLinksForPublishFilesIfPossible=true
3) Allows MSBuild's copy task(s) to try again without failing on the first encounter.
  • /p:CopyRetryCount=10
  • /p:CopyRetryDelayMilliseconds=1000
  • /p:OverwriteReadOnlyFiles=true