diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/RemoveDirFixed.cs b/src/Xamarin.Android.Build.Tasks/Tasks/RemoveDirFixed.cs index bcc8ff12ed5..b0b43e2b2c4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/RemoveDirFixed.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/RemoveDirFixed.cs @@ -42,8 +42,15 @@ public class RemoveDirFixed : AndroidTask { public override string TaskPrefix => "RDF"; - const int ERROR_ACCESS_DENIED = -2147024891; - const int ERROR_SHARING_VIOLATION = -2147024864; + const int ERROR_ACCESS_DENIED = -2147024891; // 0x80070005 + const int ERROR_SHARING_VIOLATION = -2147024864; // 0x80070020 + // On Unix, .NET maps `ENOTEMPTY` from `rmdir(2)` to this Win32 HResult, + // so the same constant covers both Windows and Unix sources of + // "Directory not empty". This is observed on NTFS volumes mounted via + // the Linux `ntfs3` driver, where directory metadata can momentarily + // report children that have just been unlinked, but is not specific + // to that filesystem. + const int ERROR_DIR_NOT_EMPTY = -2147024751; // 0x80070091 public override bool RunTask () { @@ -80,7 +87,7 @@ public override bool RunTask () case UnauthorizedAccessException: case IOException: int code = Marshal.GetHRForException(e); - if ((code != ERROR_ACCESS_DENIED && code != ERROR_SHARING_VIOLATION) || retryCount >= attempts) { + if ((code != ERROR_ACCESS_DENIED && code != ERROR_SHARING_VIOLATION && code != ERROR_DIR_NOT_EMPTY) || retryCount >= attempts) { throw; }; break;