Skip to content

FileStreamFactoryMock re-opens the path behind a SafeFileHandle instead of adopting the handle #1086

Description

@Mpdreamz

A real FileStream constructed from a SafeFileHandle adopts the handle: the file is not opened a second time, no new file share is taken, and the stream can therefore never conflict with whatever already holds the file open.

FileStreamFactoryMock instead resolves the handle to a path through ISafeFileHandleStrategy and opens that path again, taking a fresh file share from SafeFileHandleMock.Share. Layering a stream on a handle can consequently fail with a sharing violation where the real file system succeeds.

Reproduction

MockFileSystem fileSystem = new(o => o.SimulatingOperatingSystem(SimulationMode.Windows));
fileSystem.File.WriteAllText("file.txt", "some content");
fileSystem.WithSafeFileHandleStrategy(
    new DefaultSafeFileHandleStrategy(_ => new SafeFileHandleMock("file.txt")));
SafeFileHandle handle = new(new IntPtr(0x1234), ownsHandle: false);

// something else holds the file open exclusively
using FileSystemStream exclusive = fileSystem.File.Open("file.txt",
    FileMode.Open, FileAccess.Read, FileShare.None);

using FileSystemStream adopted = fileSystem.FileStream.New(handle, FileAccess.Read);
// IOException: The process cannot access the file ... because it is being used by another process.

A real FileStream over a real handle succeeds here, because it takes no share.

Expected

IFileStreamFactory.New(SafeFileHandle, ...) — all three overloads — should not take a file share, matching the adoption semantics of the underlying type.

Note on ignoreFileShare

IStorageContainer.RequestAccess already has an ignoreFileShare parameter, but it is a no-op on Windows: FileHandle.GrantAccess only consults it inside if (!_fileSystem.Execute.IsWindows). That may be deliberate, so rather than change its meaning — three call sites in InMemoryStorage rely on it — the attached PR skips taking a share altogether for the adopting case, using the existing FileHandle.Ignore.

Worth deciding separately whether ignoreFileShare being inert on Windows is itself a bug.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions