Beispiel #1
0
        public bool Unregister(WaitHandle waitObject)
        {
            // Hold the lock during the synchronous part of Unregister (as in CoreCLR)
            using (LockHolder.Hold(_lock))
            {
                if (!_unregistering)
                {
                    // Ensure callbacks will not call SetThreadpoolWait anymore
                    _unregistering = true;

                    // Cease queueing more callbacks
                    Interop.Kernel32.SetThreadpoolWait(_tpWait, IntPtr.Zero, IntPtr.Zero);

                    // Should we wait for callbacks synchronously? Note that we treat the zero handle as the asynchronous case.
                    SafeWaitHandle?safeWaitHandle = waitObject?.SafeWaitHandle;
                    bool           blocking       = ((safeWaitHandle != null) && (safeWaitHandle.DangerousGetHandle() == new IntPtr(-1)));

                    if (blocking)
                    {
                        FinishUnregistering();
                    }
                    else
                    {
                        // Wait for callbacks and dispose resources asynchronously
                        ThreadPool.QueueUserWorkItem(FinishUnregisteringAsync, safeWaitHandle);
                    }

                    return(true);
                }
            }
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Obtains all of the corresponding safe wait handles and adds a ref to each. Since the <see cref="SafeWaitHandle"/>
        /// property is publically modifiable, this makes sure that we add and release refs one the same set of safe wait
        /// handles to keep them alive during a multi-wait operation.
        /// </summary>
        private static void ObtainSafeWaitHandles(
            ReadOnlySpan <WaitHandle> waitHandles,
            Span <SafeWaitHandle?> safeWaitHandles,
            Span <IntPtr> unsafeWaitHandles)
        {
            Debug.Assert(waitHandles != null);
            Debug.Assert(waitHandles.Length > 0);
            Debug.Assert(waitHandles.Length <= MaxWaitHandles);

            bool           lastSuccess        = true;
            SafeWaitHandle?lastSafeWaitHandle = null;

            try
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    WaitHandle waitHandle = waitHandles[i];
                    if (waitHandle == null)
                    {
                        throw new ArgumentNullException("waitHandles[" + i + ']', SR.ArgumentNull_ArrayElement);
                    }

                    SafeWaitHandle safeWaitHandle = waitHandle._waitHandle ??
                                                    // Throw ObjectDisposedException for backward compatibility even though it is not representative of the issue
                                                    throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic);

                    lastSafeWaitHandle = safeWaitHandle;
                    lastSuccess        = false;
                    safeWaitHandle.DangerousAddRef(ref lastSuccess);
                    safeWaitHandles[i]   = safeWaitHandle;
                    unsafeWaitHandles[i] = safeWaitHandle.DangerousGetHandle();
                }
            }
            catch
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    SafeWaitHandle?safeWaitHandle = safeWaitHandles[i];
                    if (safeWaitHandle == null)
                    {
                        break;
                    }
                    safeWaitHandle.DangerousRelease();
                    safeWaitHandles[i] = null;
                    if (safeWaitHandle == lastSafeWaitHandle)
                    {
                        lastSafeWaitHandle = null;
                        lastSuccess        = true;
                    }
                }

                if (!lastSuccess)
                {
                    Debug.Assert(lastSafeWaitHandle != null);
                    lastSafeWaitHandle.DangerousRelease();
                }

                throw;
            }
        }
Beispiel #3
0
        public static OpenExistingResult OpenNamedMutex(string name, out SafeWaitHandle?result)
        {
            OpenExistingResult status = WaitableObject.OpenNamedMutex(name, out WaitableObject? mutex);

            result = status == OpenExistingResult.Success ? NewHandle(mutex !) : null;
            return(status);
        }
 internal SafeProcessHandle(int processId, SafeWaitHandle handle) :
     this(handle.DangerousGetHandle(), ownsHandle : true)
 {
     ProcessId = processId;
     _handle   = handle;
     handle.DangerousAddRef(ref _releaseRef);
 }
Beispiel #5
0
        private static bool SignalAndWait(WaitHandle toSignal, WaitHandle toWaitOn, int millisecondsTimeout)
        {
            if (toSignal == null)
            {
                throw new ArgumentNullException(nameof(toSignal));
            }
            if (toWaitOn == null)
            {
                throw new ArgumentNullException(nameof(toWaitOn));
            }
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
            }

            // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
            // to ensure that one instance is used in all places in this method
            SafeWaitHandle?safeWaitHandleToSignal = toSignal._waitHandle;
            SafeWaitHandle?safeWaitHandleToWaitOn = toWaitOn._waitHandle;

            if (safeWaitHandleToSignal == null || safeWaitHandleToWaitOn == null)
            {
                // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue
                throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic);
            }

            bool successSignal = false, successWait = false;

            try
            {
                safeWaitHandleToSignal.DangerousAddRef(ref successSignal);
                safeWaitHandleToWaitOn.DangerousAddRef(ref successWait);

                int ret = SignalAndWaitCore(
                    safeWaitHandleToSignal.DangerousGetHandle(),
                    safeWaitHandleToWaitOn.DangerousGetHandle(),
                    millisecondsTimeout);

                if (ret == WaitAbandoned)
                {
                    throw new AbandonedMutexException();
                }

                return(ret != WaitTimeout);
            }
            finally
            {
                if (successWait)
                {
                    safeWaitHandleToWaitOn.DangerousRelease();
                }
                if (successSignal)
                {
                    safeWaitHandleToSignal.DangerousRelease();
                }
            }
        }
        /// <summary>
        /// Sets the native operating system handle
        /// </summary>
        /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
        /// <param name="value">A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</param>
        public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle?value)
        {
            if (waitHandle == null)
            {
                throw new ArgumentNullException(nameof(waitHandle));
            }

            waitHandle.SafeWaitHandle = value;
        }
Beispiel #7
0
        /// <summary>
        /// Sets the native operating system handle
        /// </summary>
        /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
        /// <param name="value">A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</param>
        public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle?value)
        {
            if (waitHandle == null)
            {
                throw new ArgumentNullException(nameof(waitHandle));
            }

            waitHandle.SafeWaitHandle = value !; // TODO-NULLABLE: Remove ! when nullable attributes are respected
        }
Beispiel #8
0
        private void FinishUnregisteringAsync(object?waitObject)
        {
            FinishUnregistering();

            // Signal the provided wait object
            SafeWaitHandle?safeWaitHandle = (SafeWaitHandle?)waitObject;

            if ((safeWaitHandle != null) && !safeWaitHandle.IsInvalid)
            {
                Interop.Kernel32.SetEvent(safeWaitHandle);
            }
        }
Beispiel #9
0
        private void CreateMutexCore(bool initiallyOwned, string?name, out bool createdNew)
        {
            if (name != null)
            {
                SafeWaitHandle?safeWaitHandle = WaitSubsystem.CreateNamedMutex(initiallyOwned, name, out createdNew);
                if (safeWaitHandle == null)
                {
                    throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
                }
                SafeWaitHandle = safeWaitHandle;
                return;
            }

            SafeWaitHandle = WaitSubsystem.NewMutex(initiallyOwned);
            createdNew     = true;
        }
Beispiel #10
0
        private static SafeWaitHandle NewHandle(WaitableObject waitableObject)
        {
            IntPtr         handle         = HandleManager.NewHandle(waitableObject);
            SafeWaitHandle?safeWaitHandle = null;

            try
            {
                safeWaitHandle = new SafeWaitHandle(handle, ownsHandle: true);
                return(safeWaitHandle);
            }
            finally
            {
                if (safeWaitHandle == null)
                {
                    HandleManager.DeleteHandle(handle);
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle.
        /// </summary>
        private void SignalUserWaitHandle()
        {
            _callbackLock.VerifyIsLocked();
            SafeWaitHandle?handle      = UserUnregisterWaitHandle;
            IntPtr         handleValue = UserUnregisterWaitHandleValue;

            try
            {
                if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1))
                {
                    Debug.Assert(handleValue == handle !.DangerousGetHandle());
                    EventWaitHandle.Set(handle);
                }
            }
            finally
            {
                handle?.DangerousRelease();
                _callbacksComplete?.Set();
                _unregistered = true;
            }
        }
        /// <summary>
        /// Sets the native operating system handle
        /// </summary>
        /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
        /// <param name="value">A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</param>
        public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle?value)
        {
            ArgumentNullException.ThrowIfNull(waitHandle);

            waitHandle.SafeWaitHandle = value;
        }
 public static ISafeWaitHandle?ToInterface(this SafeWaitHandle?handle)
 {
     return(handle == null ? null : new SafeWaitHandleAdapter(handle));
 }