public virtual bool WaitOne() { CheckDisposed(); bool release = false; try { safe_wait_handle.DangerousAddRef(ref release); return(WaitOne_internal(safe_wait_handle.DangerousGetHandle(), Timeout.Infinite, false)); } finally { if (release) { safe_wait_handle.DangerousRelease(); } } }
internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle) { SafeWaitHandle handle = socketAndEventHandle._waitHandle.GetSafeWaitHandle(); bool b = false; try { handle.DangerousAddRef(ref b); } catch { if (b) { handle.DangerousRelease(); socketAndEventHandle._waitHandle = null; b = false; } } finally { if (b) { handle.Dispose(); } } }
private bool JoinInternal(int millisecondsTimeout) { // This method assumes the thread has been started Debug.Assert(!GetThreadStateBit(ThreadState.Unstarted) || (millisecondsTimeout == 0)); SafeWaitHandle waitHandle = _stopped.SafeWaitHandle; // If an OS thread is terminated and its Thread object is resurrected, waitHandle may be finalized and closed if (waitHandle.IsClosed) { return(true); } // Prevent race condition with the finalizer try { waitHandle.DangerousAddRef(); } catch (ObjectDisposedException) { return(true); } try { return(_stopped.WaitOne(millisecondsTimeout)); } finally { waitHandle.DangerousRelease(); } }
/// <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 SafeWaitHandle[] ObtainSafeWaitHandles( RuntimeThread currentThread, WaitHandle[] waitHandles, out SafeWaitHandle[] rentedSafeWaitHandles) { Debug.Assert(currentThread == RuntimeThread.CurrentThread); Debug.Assert(waitHandles != null); Debug.Assert(waitHandles.Length > 0); Debug.Assert(waitHandles.Length <= MaxWaitHandles); rentedSafeWaitHandles = currentThread.RentWaitedSafeWaitHandleArray(waitHandles.Length); SafeWaitHandle[] safeWaitHandles = rentedSafeWaitHandles ?? new SafeWaitHandle[waitHandles.Length]; bool success = false; 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; if (safeWaitHandle == null) { // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); } safeWaitHandle.DangerousAddRef(); safeWaitHandles[i] = safeWaitHandle; } success = true; } finally { if (!success) { for (int i = 0; i < waitHandles.Length; ++i) { SafeWaitHandle safeWaitHandle = safeWaitHandles[i]; if (safeWaitHandle == null) { break; } safeWaitHandle.DangerousRelease(); safeWaitHandles[i] = null; } if (rentedSafeWaitHandles != null) { currentThread.ReturnWaitedSafeWaitHandleArray(rentedSafeWaitHandles); } } } return(safeWaitHandles); }
internal RegisteredWaitHandle(SafeWaitHandle waitHandle, _ThreadPoolWaitOrTimerCallback callbackHelper, uint millisecondsTimeout, bool repeating) { _lock = new Lock(); // Protect the handle from closing while we are waiting on it (VSWhidbey 285642) waitHandle.DangerousAddRef(); _waitHandle = waitHandle; _callbackHelper = callbackHelper; _millisecondsTimeout = millisecondsTimeout; _repeating = repeating; // Allocate _gcHandle and _tpWait as the last step and make sure they are never leaked _gcHandle = GCHandle.Alloc(this); _tpWait = Interop.mincore.CreateThreadpoolWait( AddrofIntrinsics.AddrOf <Interop.mincore.WaitCallback>(RegisteredWaitCallback), (IntPtr)_gcHandle, IntPtr.Zero); if (_tpWait == IntPtr.Zero) { _gcHandle.Free(); throw new OutOfMemoryException(); } }
internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle) { SafeWaitHandle safeWaitHandle = socketAndEventHandle.waitHandle.SafeWaitHandle; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { safeWaitHandle.DangerousAddRef(ref success); } catch { if (success) { safeWaitHandle.DangerousRelease(); socketAndEventHandle.waitHandle = null; success = false; } } finally { if (success) { safeWaitHandle.Dispose(); } } }
internal static int TryMsgWaitForMultipleObjects(SafeWaitHandle handle, bool waitAll, int milliseconds, int wakeMask, ref int lastWin32Error) { int terminationEvent; if (handle == null) { terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(0, null, waitAll, milliseconds, wakeMask); lastWin32Error = Marshal.GetLastWin32Error(); } else { bool fRelease = false; try { handle.DangerousAddRef(ref fRelease); IntPtr[] handles = { handle.DangerousGetHandle() }; terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(1, handles, waitAll, milliseconds, wakeMask); lastWin32Error = Marshal.GetLastWin32Error(); } finally { if (fRelease) { handle.DangerousRelease(); } } } return(terminationEvent); }
/// <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; } }
internal static int TryMsgWaitForMultipleObjects(SafeWaitHandle handle, bool waitAll, int milliseconds, int wakeMask, ref int lastWin32Error) { int terminationEvent; if (handle == null) { terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(0, null, waitAll, milliseconds, wakeMask); lastWin32Error = Marshal.GetLastWin32Error(); } else { #pragma warning disable SYSLIB0004 // The Constrained Execution Region (CER) feature is not supported. RuntimeHelpers.PrepareConstrainedRegions(); #pragma warning restore SYSLIB0004 // The Constrained Execution Region (CER) feature is not supported. bool fRelease = false; try { handle.DangerousAddRef(ref fRelease); IntPtr[] handles = { handle.DangerousGetHandle() }; terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(1, handles, waitAll, milliseconds, wakeMask); lastWin32Error = Marshal.GetLastWin32Error(); } finally { if (fRelease) { handle.DangerousRelease(); } } } return(terminationEvent); }
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(); } } }
public void SetDependencies(SafeWaitHandle waitHandle) { bool darSuccess = false; waitHandle.DangerousAddRef(ref darSuccess); Debug.Assert(darSuccess == true); _waitHandle = waitHandle; }
internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle) { SafeWaitHandle handle = socketAndEventHandle._waitHandle.GetSafeWaitHandle(); bool ignore = false; handle.DangerousAddRef(ref ignore); // TODO #3562: Investigate if this pattern is still correct. // Note that the handle still has a reference from the above DangerousAddRef. handle.Dispose(); }
internal static bool Set(SafeWaitHandle waitHandle) { waitHandle.DangerousAddRef(); try { WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle()); return(true); } finally { waitHandle.DangerousRelease(); } }
internal static int WaitOneNative(SafeWaitHandle waitableSafeHandle, long millisecondsTimeout) { Debug.Assert(millisecondsTimeout >= -1 && millisecondsTimeout <= int.MaxValue); waitableSafeHandle.DangerousAddRef(); try { return(LowLevelThread.WaitForSingleObject(waitableSafeHandle.DangerousGetHandle(), (int)millisecondsTimeout)); } finally { waitableSafeHandle.DangerousRelease(); } }
public static bool ResetEvent(SafeWaitHandle handle) { bool release = false; try { handle.DangerousAddRef(ref release); return(ResetEvent_internal(handle.DangerousGetHandle())); } finally { if (release) { handle.DangerousRelease(); } } }
internal static bool Set(SafeWaitHandle waitHandle) { bool release = false; try { waitHandle.DangerousAddRef(ref release); return(SetEventInternal(waitHandle.DangerousGetHandle())); } finally { if (release) { waitHandle.DangerousRelease(); } } }
private void SignalNoCallbacksRunning() { SafeWaitHandle waitHandle = _notifyWhenNoCallbacksRunning.SafeWaitHandle; waitHandle.DangerousAddRef(); try { WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle()); } finally { waitHandle.DangerousRelease(); } }
private SafeWaitHandle ValidateHandle() { // 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 waitHandle = SafeWaitHandle; if (waitHandle.IsInvalid) { ThrowInvalidHandleException(); } waitHandle.DangerousAddRef(); return(waitHandle); }
static int SignalAndWaitOne(SafeWaitHandle waitHandleToSignal,SafeWaitHandle waitHandleToWaitOn, int millisecondsTimeout, bool hasThreadAffinity, bool exitContext) { bool releaseHandleToSignal = false, releaseHandleToWaitOn = false; try { waitHandleToSignal.DangerousAddRef (ref releaseHandleToSignal); waitHandleToWaitOn.DangerousAddRef (ref releaseHandleToWaitOn); return SignalAndWait_Internal (waitHandleToSignal.DangerousGetHandle (), waitHandleToWaitOn.DangerousGetHandle (), millisecondsTimeout); } finally { if (releaseHandleToSignal) waitHandleToSignal.DangerousRelease (); if (releaseHandleToWaitOn) waitHandleToWaitOn.DangerousRelease (); } }
private SafeWaitHandle ValidateHandle(out bool success) { // 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 waitHandle = SafeWaitHandle; if (waitHandle.IsInvalid) { throw new InvalidOperationException(); } success = false; waitHandle.DangerousAddRef(ref success); return(waitHandle); }
private bool WaitOneNoCheck(int millisecondsTimeout) { Debug.Assert(millisecondsTimeout >= -1); // 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 waitHandle = _waitHandle; if (waitHandle == null) { // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); } bool success = false; try { int waitResult; waitHandle.DangerousAddRef(ref success); SynchronizationContext context = SynchronizationContext.Current; if (context != null && context.IsWaitNotificationRequired()) { waitResult = context.Wait(new[] { waitHandle.DangerousGetHandle() }, false, millisecondsTimeout); } else { waitResult = WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout); } if (waitResult == WaitAbandoned) { throw new AbandonedMutexException(); } return(waitResult != WaitTimeout); } finally { if (success) { waitHandle.DangerousRelease(); } } }
public void Wait(WaitHandle launchCompleteHandle, CancellationTokenSource cancellationSource) { int hr; SafeWaitHandle safeWaitHandle = launchCompleteHandle.SafeWaitHandle; bool addRefSucceeded = false; try { safeWaitHandle.DangerousAddRef(ref addRefSucceeded); if (!addRefSucceeded) { throw new ObjectDisposedException("launchCompleteHandle"); } IntPtr nativeHandle = safeWaitHandle.DangerousGetHandle(); IntPtr[] handles = { nativeHandle }; uint waitResult; hr = _messagePump.ModalWaitForObjects(handles, (uint)handles.Length, out waitResult); if (hr == 0) { return; } else if (hr == VSConstants.E_PENDING || hr == VSConstants.E_ABORT) { // E_PENDING: user canceled // E_ABORT: application exit cancellationSource.Cancel(); throw new OperationCanceledException(); } else { Debug.Fail("Unexpected result from ModalWaitForObjects"); Marshal.ThrowExceptionForHR(hr); } } finally { if (addRefSucceeded) { safeWaitHandle.DangerousRelease(); } } }
private bool JoinCore(int millisecondsTimeout) { SafeWaitHandle waitHandle = _osHandle; int result; waitHandle.DangerousAddRef(); try { result = WaitHandle.WaitForSingleObject(waitHandle.DangerousGetHandle(), millisecondsTimeout); } finally { waitHandle.DangerousRelease(); } return(result == (int)Interop.Constants.WaitObject0); }
private bool JoinInternal(int millisecondsTimeout) { // This method assumes the thread has been started Debug.Assert(!GetThreadStateBit(ThreadState.Unstarted) || (millisecondsTimeout == 0)); SafeWaitHandle waitHandle = _osHandle; // If an OS thread is terminated and its Thread object is resurrected, _osHandle may be finalized and closed if (waitHandle.IsClosed) { return(true); } // Handle race condition with the finalizer try { waitHandle.DangerousAddRef(); } catch (ObjectDisposedException) { return(true); } try { int result; if (millisecondsTimeout == 0) { result = (int)Interop.Kernel32.WaitForSingleObject(waitHandle.DangerousGetHandle(), 0); } else { result = WaitHandle.WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout); } return(result == (int)Interop.Kernel32.WAIT_OBJECT_0); } finally { waitHandle.DangerousRelease(); } }
private int ReleaseCore(int releaseCount) { // 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 waitHandle = _waitHandle; if (waitHandle == null) { ThrowInvalidHandleException(); } waitHandle.DangerousAddRef(); try { return(ReleaseCore(waitHandle.DangerousGetHandle(), releaseCount)); } finally { waitHandle.DangerousRelease(); } }
public bool Reset() { // The field value is modifiable via <see cref="SafeWaitHandle"/>, save it locally to ensure that ref modification // is done on the same instance SafeWaitHandle waitHandle = _waitHandle; if (waitHandle == null) { ThrowInvalidHandleException(); } waitHandle.DangerousAddRef(); try { return(ResetCore(_waitHandle.DangerousGetHandle())); } finally { waitHandle.DangerousRelease(); } }
public void ReleaseMutex() { // 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 waitHandle = _waitHandle; if (waitHandle == null) { ThrowInvalidHandleException(); } waitHandle.DangerousAddRef(); try { WaitSubsystem.ReleaseMutex(waitHandle.DangerousGetHandle()); } finally { waitHandle.DangerousRelease(); } }
private bool WaitOneCore(int millisecondsTimeout, bool interruptible = true) { Debug.Assert(millisecondsTimeout >= -1); // 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 waitHandle = _waitHandle; if (waitHandle == null) { // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); } waitHandle.DangerousAddRef(); try { return(WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout, interruptible)); } finally { waitHandle.DangerousRelease(); } }
private void SignalNoCallbacksRunning() { object toSignal = _notifyWhenNoCallbacksRunning; Debug.Assert(toSignal is WaitHandle || toSignal is Task <bool>); if (toSignal is WaitHandle wh) { SafeWaitHandle waitHandle = wh.SafeWaitHandle; waitHandle.DangerousAddRef(); try { WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle()); } finally { waitHandle.DangerousRelease(); } } else { ((Task <bool>)toSignal).TrySetResult(true); } }
/////////////////////////////////////////////////////////////////////////////////////////////// // // WARNING: Contains a "Constrained Execution Region", modify carefully. // private static ReturnCode WaitForSingleHandle( WaitHandle waitHandle, int milliseconds, bool userInterface, ref uint returnValue, ref Result error ) { SafeWaitHandle safeWaitHandle = null; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { if (waitHandle == null) { error = "invalid wait handle"; return(ReturnCode.Error); } safeWaitHandle = waitHandle.SafeWaitHandle; if (safeWaitHandle == null) { error = "invalid safe wait handle"; return(ReturnCode.Error); } safeWaitHandle.DangerousAddRef(ref success); if (!success) { error = "failed to add reference to safe wait handle"; return(ReturnCode.Error); } IntPtr[] handles = { safeWaitHandle.DangerousGetHandle() }; if (handles[0] == IntPtr.Zero) { error = "failed to get native handle from safe wait handle"; return(ReturnCode.Error); } if (userInterface) { returnValue = UnsafeNativeMethods.MsgWaitForMultipleObjectsEx( 1, handles, (uint)milliseconds, UnsafeNativeMethods.QS_ALLINPUT, UnsafeNativeMethods.MWMO_DEFAULT); } else { returnValue = UnsafeNativeMethods.WaitForMultipleObjectsEx( 1, handles, false, (uint)milliseconds, true); } return(ReturnCode.Ok); } catch (Exception e) { if (traceException) { TraceOps.DebugTrace( e, typeof(WindowOps).Name, TracePriority.NativeError); } error = e; } finally { if (success) { safeWaitHandle.DangerousRelease(); success = false; } } return(ReturnCode.Error); }