Skip to content

FileStream does not work with P/Invoked file descriptor and SafeFileHandle #12783

@zivkan

Description

@zivkan

Steps to Reproduce

using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace linuxwriter
{
    class Program
    {
        static void Main()
        {
            int fd;
            try
            {
                fd = creat("file.txt", Convert.ToInt32("777", 8));
            }
            catch (Exception exception)
            {
                throw new Exception($"Error trying to create file: {exception.Message}");
            }

            if (fd == -1)
            {
                using (File.Create("file.txt"))
                {
                    // File.Create() should have thrown an exception
                }
                File.Delete("file.txt");
                throw new InvalidOperationException($"libc creat failed, but File.Create did not");
            }

            var sfh = new SafeFileHandle((IntPtr)fd, ownsHandle: true);

            using (var stream = new FileStream(sfh, FileAccess.ReadWrite))
            using (var writer = new StreamWriter(stream))
            {
                writer.WriteLine("Normally a binary file extracted from a zip");
            }
        }

        [DllImport("libc", SetLastError = true)]
        private static extern int creat(string pathname, int mode);
    }
}

Current Behavior

The file is created with the correct permissions, however, when attempting to use the file descriptor in a FileStream, it crashes with the following error and stack trace:

Unhandled Exception:
System.IO.IOException: Invalid handle to path "[Unknown]"
  at System.IO.FileStream.Init (Microsoft.Win32.SafeHandles.SafeFileHandle safeHandle, System.IO.FileAccess access, System.Boolean ownsHandle, System.Int32 bufferSize, System.Boolean isAsync, System.Boolean isConsoleWrapper) [0x0007f] in <8f2c484307284b51944a1a13a14c0266>:0
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize, System.Boolean isAsync) [0x00011] in <8f2c484307284b51944a1a13a14c0266>:0
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access) [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0
  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (Microsoft.Win32.SafeHandles.SafeFileHandle,System.IO.FileAccess)
  at linuxwriter.Program.Main () [0x0007c] in <85036eb2b84e47d0aa546e0d393fb85b>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.IOException: Invalid handle to path "[Unknown]"
  at System.IO.FileStream.Init (Microsoft.Win32.SafeHandles.SafeFileHandle safeHandle, System.IO.FileAccess access, System.Boolean ownsHandle, System.Int32 bufferSize, System.Boolean isAsync, System.Boolean isConsoleWrapper) [0x0007f] in <8f2c484307284b51944a1a13a14c0266>:0
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize, System.Boolean isAsync) [0x00011] in <8f2c484307284b51944a1a13a14c0266>:0
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access) [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0
  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (Microsoft.Win32.SafeHandles.SafeFileHandle,System.IO.FileAccess)
  at linuxwriter.Program.Main () [0x0007c] in <85036eb2b84e47d0aa546e0d393fb85b>:0

Expected Behavior

Program should write to the file and close the file descriptor before exiting normally. FYI this code works as I expected with .NET Core

On which platforms did you notice this

[x] Linux

I haven't tried Mac, but this is not relevant for Windows as this code is P/Invoking a POSIX method to set permission bits that don't exist in filesystems on Windows.

Version Used:

Mono JIT compiler version 4.6.2 (Debian 4.6.2.7+dfsg-1ubuntu1)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        LLVM:          supported, not enabled.
        GC:            sgen

Stacktrace

see above.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions