Skip to content

Commit

Permalink
Improve error handling if directory not found on Linux/macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
paulirwin committed May 15, 2024
1 parent 2682952 commit 21c7196
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
22 changes: 18 additions & 4 deletions src/Lucene.Net/Support/IO/PosixFsyncSupport.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Lucene.Net.Util;
using System;
using System.IO;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -46,6 +47,9 @@ internal static class PosixFsyncSupport
// https://opensource.apple.com/source/xnu/xnu-6153.81.5/bsd/sys/fcntl.h.auto.html
private const int F_FULLFSYNC = 51;

private const int EACCES = 13;
private const int ENOENT = 2;

public static void Fsync(string path, bool isDir)
{
using DescriptorWrapper handle = new DescriptorWrapper(path, isDir);
Expand All @@ -63,7 +67,14 @@ public DescriptorWrapper(string path, bool isDir)
if (fd == -1)
{
int error = Marshal.GetLastWin32Error();
throw new IOException($"Unable to open path, error: 0x{error:x8}", error);

throw error switch
{
ENOENT when isDir => new DirectoryNotFoundException($"Directory/path not found: {path}"),
ENOENT => new FileNotFoundException($"File not found: {path}"),
EACCES => new UnauthorizedAccessException($"Access denied to {(isDir ? "directory" : "file")}: {path}"),
_ => new IOException($"Unable to open path, error: 0x{error:x8}", error)
};
}
}

Expand All @@ -74,20 +85,23 @@ public void Flush()
{
if (fcntl(fd, F_FULLFSYNC, 0) == -1)
{
throw new IOException("fcntl failed", Marshal.GetLastWin32Error());
int error = Marshal.GetLastWin32Error();
throw new IOException($"fcntl failed, error: 0x{error:x8}", error);
}
}
else if (fsync(fd) == -1)
{
throw new IOException("fsync failed", Marshal.GetLastWin32Error());
int error = Marshal.GetLastWin32Error();
throw new IOException($"fsync failed, error: 0x{error:x8}", error);
}
}

public void Dispose()
{
if (close(fd) == -1)
{
throw new IOException("close failed", Marshal.GetLastWin32Error());
int error = Marshal.GetLastWin32Error();
throw new IOException($"close failed, error: 0x{error:x8}", error);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Lucene.Net/Support/IO/WindowsFsyncSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ public HandleWrapper(string path, bool isDir)
{
int error = Marshal.GetLastWin32Error();

throw error switch {
throw error switch
{
ERROR_FILE_NOT_FOUND => new FileNotFoundException($"File not found: {path}"),
ERROR_PATH_NOT_FOUND => new DirectoryNotFoundException($"Directory/path not found: {path}"),
ERROR_ACCESS_DENIED => new UnauthorizedAccessException($"Access denied to {(isDir ? "directory" : "file")}: {path}"),
Expand Down
24 changes: 11 additions & 13 deletions src/Lucene.Net/Util/IOUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -554,22 +554,20 @@ public static void Fsync(string fileToSync, bool isDir)
PosixFsyncSupport.Fsync(fileToSync, isDir);
}
}
catch (Exception e) when (e.IsIOException())
catch (Exception e) when (e.IsIOException() && isDir && e is not DirectoryNotFoundException)
{
if (isDir)
{
if (Debugging.AssertsEnabled)
{
Debugging.Assert((Constants.LINUX || Constants.MAC_OS_X) == false,
"On Linux and MacOSX fsyncing a directory should not throw IOException, we just don't want to rely on that in production (undocumented). Got: {0}",
e);
}
// LUCENENET specific - make catch specific to IOExceptions when it's a directory,
// but allow DirectoryNotFoundException to pass through as an equivalent would normally be
// thrown by the FileChannel.open call in Java which is outside the try block.

// Ignore exception if it is a directory
return;
if (Debugging.AssertsEnabled)
{
Debugging.Assert((Constants.LINUX || Constants.MAC_OS_X) == false,
"On Linux and MacOSX fsyncing a directory should not throw IOException, we just don't want to rely on that in production (undocumented). Got: {0}",
e);
}
// Throw original exception
throw;

// Ignore exception if it is a directory
}
}
}
Expand Down

0 comments on commit 21c7196

Please sign in to comment.