protected override bool ReleaseHandle()
{
// When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add
// an advisory lock. This lock should be removed via closing the file descriptor, but close can be
// interrupted, and we don't retry closes. As such, we could end up leaving the file locked,
// which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively
// try to release the lock before we close the handle. (If it's not locked, there's no behavioral
// problem trying to unlock it.)
Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors
// Close the descriptor. Although close is documented to potentially fail with EINTR, we never want
// to retry, as the descriptor could actually have been closed, been subsequently reassigned, and
// be in use elsewhere in the process. Instead, we simply check whether the call was successful.
int result = Interop.Sys.Close(handle);
#if DEBUG
if (result != 0)
{
Debug.Fail(string.Format(
"Close failed with result {0} and error {1}",
result, Interop.Sys.GetLastErrorInfo()));
}
#endif
return result == 0;
}