/// <summary> /// Helper for making system calls that involve the stream's file descriptor. /// System calls are expected to return greather than or equal to zero on success, /// and less than zero on failure. In the case of failure, errno is expected to /// be set to the relevant error code. /// </summary> /// <typeparam name="TArg1">Specifies the type of an argument to the system call.</typeparam> /// <typeparam name="TArg2">Specifies the type of another argument to the system call.</typeparam> /// <param name="sysCall">A delegate that invokes the system call.</param> /// <param name="arg1">The first argument to be passed to the system call, after the file descriptor.</param> /// <param name="arg2">The second argument to be passed to the system call.</param> /// <param name="throwOnError">true to throw an exception if a non-interuption error occurs; otherwise, false.</param> /// <returns>The return value of the system call.</returns> /// <remarks> /// Arguments are expected to be passed via <paramref name="arg1"/> and <paramref name="arg2"/> /// so as to avoid delegate and closure allocations at the call sites. /// </remarks> private long SysCall <TArg1, TArg2>( Func <int, TArg1, TArg2, long> sysCall, TArg1 arg1 = default(TArg1), TArg2 arg2 = default(TArg2), bool throwOnError = true) { SafeFileHandle handle = _fileHandle; Debug.Assert(sysCall != null); Debug.Assert(handle != null); bool gotRefOnHandle = false; try { // Get the file descriptor from the handle. We increment the ref count to help // ensure it's not closed out from under us. handle.DangerousAddRef(ref gotRefOnHandle); Debug.Assert(gotRefOnHandle); int fd = (int)handle.DangerousGetHandle(); Debug.Assert(fd >= 0); // System calls may fail due to EINTR (signal interruption). We need to retry in those cases. while (true) { long result = sysCall(fd, arg1, arg2); if (result < 0) { Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); if (errorInfo.Error == Interop.Error.EINTR) { continue; } else if (throwOnError) { throw Interop.GetExceptionForIoErrno(errorInfo, _path, isDirectory: false); } } return(result); } } finally { if (gotRefOnHandle) { handle.DangerousRelease(); } else { throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); } } }
public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) : this(handle.DangerousGetHandle(), access, false, bufferSize, isAsync) { this.safeHandle = handle; }