/// <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(); } } }
public void Disconnect() { if (should_close_handle) { Syscall.fclose(handle.DangerousGetHandle()); } }
/// <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(); } } }
/// <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); // 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) { int errno = Marshal.GetLastWin32Error(); if (errno == Interop.Errors.EINTR) { continue; } else { throw Interop.GetExceptionForIoErrno(errno); } } return(result); } } finally { if (gotRefOnHandle) { handle.DangerousRelease(); } } }
/// <summary> /// Creates a cancellation registration. This creates a pipe that'll have one end written to /// when cancellation is requested. The other end can be poll'd to see when cancellation has occurred. /// </summary> private static unsafe DescriptorCancellationRegistration RegisterForCancellation(CancellationToken cancellationToken) { Debug.Assert(cancellationToken.CanBeCanceled); // Fast path: before doing any real work, throw if cancellation has already been requested cancellationToken.ThrowIfCancellationRequested(); // Create a pipe we can use to send a signal to the reader/writer // to wake it up if blocked. SafePipeHandle poll, send; CreateAnonymousPipe(HandleInheritability.None, out poll, out send); // Register a cancellation callback to send a byte to the cancellation pipe CancellationTokenRegistration reg = cancellationToken.Register(s => { SafePipeHandle sendRef = (SafePipeHandle)s; bool gotSendRef = false; try { sendRef.DangerousAddRef(ref gotSendRef); int fd = (int)sendRef.DangerousGetHandle(); byte b = 1; while (Interop.CheckIo((int)Interop.Sys.Write(fd, &b, 1))) { ; } } finally { if (gotSendRef) { sendRef.DangerousRelease(); } } }, send); // Return a disposable struct that will unregister the cancellation registration // and dispose of the pipe. return(new DescriptorCancellationRegistration(reg, poll, send)); }
public String GetClientHandleAsString() { _clientHandleExposed = true; GC.SuppressFinalize(_clientHandle); return(_clientHandle.DangerousGetHandle().ToString()); }
public String GetClientHandleAsString() { _clientHandleExposed = true; return(_clientHandle.DangerousGetHandle().ToString()); }