/// <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> /// <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> /// <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 static long SysCall( SafePipeHandle handle, Func<int, IntPtr, int, long> sysCall, IntPtr arg1 = default(IntPtr), int arg2 = default(int)) { 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); long result; while (Interop.CheckIo(result = sysCall(fd, arg1, arg2))) ; return result; } finally { if (gotRefOnHandle) { handle.DangerousRelease(); } } }
/// <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> /// <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="arg3">The third argument to be passed to the system call.</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( SafePipeHandle handle, Func<int, IntPtr, int, IntPtr, long> sysCall, IntPtr arg1 = default(IntPtr), int arg2 = default(int), IntPtr arg3 = default(IntPtr)) { 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); while (true) { long result = sysCall(fd, arg1, arg2, arg3); if (result == -1) { Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); if (errorInfo.Error == Interop.Error.EINTR) continue; if (errorInfo.Error == Interop.Error.EPIPE) State = PipeState.Broken; throw Interop.GetExceptionForIoErrno(errorInfo); } return result; } } finally { if (gotRefOnHandle) { handle.DangerousRelease(); } } }