Пример #1
0
        /// <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();
                }
            }
        }
Пример #2
0
 public void Disconnect()
 {
     if (should_close_handle)
     {
         Syscall.fclose(handle.DangerousGetHandle());
     }
 }
Пример #3
0
        /// <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();
                }
            }
        }
Пример #4
0
        /// <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();
                }
            }
        }
Пример #5
0
        /// <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));
        }
Пример #6
0
 public String GetClientHandleAsString()
 {
     _clientHandleExposed = true;
     GC.SuppressFinalize(_clientHandle);
     return(_clientHandle.DangerousGetHandle().ToString());
 }
Пример #7
0
 public String GetClientHandleAsString()
 {
     _clientHandleExposed = true;
     return(_clientHandle.DangerousGetHandle().ToString());
 }