Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / Threading / Mutex.cs / 1 / Mutex.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: Mutex ** ** ** Purpose: synchronization primitive that can also be used for interprocess synchronization ** ** =============================================================================*/ namespace System.Threading { using System; using System.Threading; using System.Runtime.CompilerServices; using System.Security.Permissions; using System.IO; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security.Principal; using System.Security; #if !FEATURE_PAL using System.Security.AccessControl; #endif [HostProtection(Synchronization=true, ExternalThreading=true)] [ComVisible(true)] public sealed class Mutex : WaitHandle { static bool dummyBool; private const int WAIT_OBJECT_0 = 0; private const int WAIT_ABANDONED_0 = 0x80; private const uint WAIT_FAILED = 0xFFFFFFFF; [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex(bool initiallyOwned, String name, out bool createdNew) #if !FEATURE_PAL : this(initiallyOwned, name, out createdNew, null) { } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public unsafe Mutex(bool initiallyOwned, String name, out bool createdNew, MutexSecurity mutexSecurity) #endif { if(null != name && System.IO.Path.MAX_PATH < name.Length) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong",name)); } Win32Native.SECURITY_ATTRIBUTES secAttrs = null; #if !FEATURE_PAL // For ACL's, get the security descriptor from the MutexSecurity. if (mutexSecurity != null) { secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); byte[] sd = mutexSecurity.GetSecurityDescriptorBinaryForm(); byte* pSecDescriptor = stackalloc byte[sd.Length]; Buffer.memcpy(sd, 0, pSecDescriptor, 0, sd.Length); secAttrs.pSecurityDescriptor = pSecDescriptor; } #endif SafeWaitHandle mutexHandle = null; bool newMutex = false; RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(mutexHandle, false); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate(object userData) { // try block RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (initiallyOwned) { cleanupInfo.inCriticalRegion = true; Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); } } int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { errorCode = CreateMutexHandle(initiallyOwned, name, secAttrs, out mutexHandle); } if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name)); __Error.WinIOError(errorCode, name); } newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS; SetHandleInternal(mutexHandle); hasThreadAffinity = true; }, cleanupCode, cleanupInfo); createdNew = newMutex; } [PrePrepareMethod] private void MutexCleanupCode(Object userData, bool exceptionThrown) { MutexCleanupInfo cleanupInfo = (MutexCleanupInfo) userData; // If hasThreadAffinity isn’t true, we’ve thrown an exception in the above try, and we must free the mutex // on this OS thread before ending our thread affninity. if(!hasThreadAffinity) { if (cleanupInfo.mutexHandle != null && !cleanupInfo.mutexHandle.IsInvalid) { if( cleanupInfo.inCriticalRegion) { Win32Native.ReleaseMutex(cleanupInfo.mutexHandle); } cleanupInfo.mutexHandle.Dispose(); } if( cleanupInfo.inCriticalRegion) { Thread.EndCriticalRegion(); Thread.EndThreadAffinity(); } } } internal class MutexCleanupInfo { internal SafeWaitHandle mutexHandle; internal bool inCriticalRegion; internal MutexCleanupInfo(SafeWaitHandle mutexHandle, bool inCriticalRegion) { this.mutexHandle = mutexHandle; this.inCriticalRegion = inCriticalRegion; } } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public Mutex(bool initiallyOwned, String name) : this(initiallyOwned, name, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex(bool initiallyOwned) : this(initiallyOwned, null, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex() : this(false, null, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private Mutex(SafeWaitHandle handle) { SetHandleInternal(handle); hasThreadAffinity = true; } [SecurityPermissionAttribute(SecurityAction.LinkDemand,Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static Mutex OpenExisting(string name) { #if !FEATURE_PAL return OpenExisting(name, MutexRights.Modify | MutexRights.Synchronize); } [SecurityPermissionAttribute(SecurityAction.LinkDemand,Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static Mutex OpenExisting(string name, MutexRights rights) { #endif // !FEATURE_PAL if (name == null) { throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName")); } if(name.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); } if(System.IO.Path.MAX_PATH < name.Length) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong",name)); } // To allow users to view & edit the ACL's, call OpenMutex // with parameters to allow us to view & edit the ACL. This will // fail if we don't have permission to view or edit the ACL's. // If that happens, ask for less permissions. #if FEATURE_PAL SafeWaitHandle myHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); #else SafeWaitHandle myHandle = Win32Native.OpenMutex((int) rights, false, name); #endif int errorCode = 0; if (myHandle.IsInvalid) { errorCode = Marshal.GetLastWin32Error(); if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode) { throw new WaitHandleCannotBeOpenedException(); } if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name)); } // this is for passed through Win32Native Errors __Error.WinIOError(errorCode,name); } return new Mutex(myHandle); } // Note: To call ReleaseMutex, you must have an ACL granting you // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001). [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public void ReleaseMutex() { if (Win32Native.ReleaseMutex(safeWaitHandle)) { Thread.EndCriticalRegion(); Thread.EndThreadAffinity(); } else { throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException")); } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) { int errorCode; bool fAffinity = false; bool fHitRace = false; bool fRetry = false; while(true) { fHitRace = false; fRetry = false; mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name); errorCode = Marshal.GetLastWin32Error(); if( !mutexHandle.IsInvalid) { break; } if( errorCode == Win32Native.ERROR_ACCESS_DENIED) { // If a mutex with the name already exists, OS will try to open it with FullAccess. // It might fail if we don't have enough access. In that case, we try to open the mutex will modify and synchronize access. // RuntimeHelpers.PrepareConstrainedRegions(); try { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { Thread.BeginThreadAffinity(); fAffinity = true; } mutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); if(!mutexHandle.IsInvalid) { errorCode = Win32Native.ERROR_ALREADY_EXISTS; #if !FEATURE_PAL if (Environment.IsW2k3) { //Enables workaround for known OS bug at //http://support.microsoft.com/default.aspx?scid=kb;en-us;889318 //Workaround suggested by NeillC (The previous workaround of a acquiring a global mutex was not secure): //1)Open the mutex twice. //2)Call WaitForMultipleObjects with bWaitAll=TRUE and a zero timeout //3)If this call returns with ERROR_INVALID_PARAMETER then the two objects are the same and you can close one and use the other //4)If it returns timeout then you hit the ---- //5)If it returns success then you hit the ---- but you have to release before close. SafeWaitHandle tempMutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); if(!tempMutexHandle.IsInvalid) { RuntimeHelpers.PrepareConstrainedRegions(); try { uint originalRetCode = 0; IntPtr mutexPtr = mutexHandle.DangerousGetHandle(); IntPtr tempMutexPtr = tempMutexHandle.DangerousGetHandle(); IntPtr[] waitHandles = new IntPtr[] {mutexPtr, tempMutexPtr}; //We directly Pinvoke to WaitForMultipleObjects for two reasons: //1. The VM method WaitForMultiple does not support doing WaitForMultipleObjects // for COM STA threads. //2. We call the method in such a way that it's guaranteed to not block, so // it should not lead to any COM pumping/rentrancy issues. originalRetCode = Win32Native.WaitForMultipleObjects(2,waitHandles,true, 0); GC.KeepAlive(waitHandles); if(originalRetCode == WAIT_FAILED) { uint retCode = (uint) Marshal.GetLastWin32Error(); BCLDebug.Assert(retCode == Win32Native.ERROR_INVALID_PARAMETER, "Expected Invalid Parameter return code"); //Some weird transient error? if(retCode != Win32Native.ERROR_INVALID_PARAMETER) { mutexHandle.Dispose(); fRetry = true; } } else { fHitRace = true; if((originalRetCode >= WAIT_OBJECT_0) && (originalRetCode < (WAIT_OBJECT_0+2))) { Win32Native.ReleaseMutex(mutexHandle); Win32Native.ReleaseMutex(tempMutexHandle); } else if((originalRetCode >= WAIT_ABANDONED_0) && (originalRetCode < (WAIT_ABANDONED_0+2))) { Win32Native.ReleaseMutex(mutexHandle); Win32Native.ReleaseMutex(tempMutexHandle); } mutexHandle.Dispose(); } } finally { tempMutexHandle.Dispose(); } } else { mutexHandle.Dispose(); fRetry = true; } } #endif //!FEATURE_PAL } else { errorCode = Marshal.GetLastWin32Error(); } } finally { if (fAffinity) Thread.EndThreadAffinity(); } if(fHitRace || fRetry) continue; // There could be a ---- here, the other owner of the mutex can free the mutex, // We need to retry creation in that case. if( errorCode != Win32Native.ERROR_FILE_NOT_FOUND) { if( errorCode == Win32Native.ERROR_SUCCESS) { errorCode = Win32Native.ERROR_ALREADY_EXISTS; } break; } } else { break; } } return errorCode; } #if !FEATURE_PAL public MutexSecurity GetAccessControl() { return new MutexSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } public void SetAccessControl(MutexSecurity mutexSecurity) { if (mutexSecurity == null) throw new ArgumentNullException("mutexSecurity"); mutexSecurity.Persist(safeWaitHandle); } #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: Mutex ** ** ** Purpose: synchronization primitive that can also be used for interprocess synchronization ** ** =============================================================================*/ namespace System.Threading { using System; using System.Threading; using System.Runtime.CompilerServices; using System.Security.Permissions; using System.IO; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security.Principal; using System.Security; #if !FEATURE_PAL using System.Security.AccessControl; #endif [HostProtection(Synchronization=true, ExternalThreading=true)] [ComVisible(true)] public sealed class Mutex : WaitHandle { static bool dummyBool; private const int WAIT_OBJECT_0 = 0; private const int WAIT_ABANDONED_0 = 0x80; private const uint WAIT_FAILED = 0xFFFFFFFF; [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex(bool initiallyOwned, String name, out bool createdNew) #if !FEATURE_PAL : this(initiallyOwned, name, out createdNew, null) { } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public unsafe Mutex(bool initiallyOwned, String name, out bool createdNew, MutexSecurity mutexSecurity) #endif { if(null != name && System.IO.Path.MAX_PATH < name.Length) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong",name)); } Win32Native.SECURITY_ATTRIBUTES secAttrs = null; #if !FEATURE_PAL // For ACL's, get the security descriptor from the MutexSecurity. if (mutexSecurity != null) { secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); byte[] sd = mutexSecurity.GetSecurityDescriptorBinaryForm(); byte* pSecDescriptor = stackalloc byte[sd.Length]; Buffer.memcpy(sd, 0, pSecDescriptor, 0, sd.Length); secAttrs.pSecurityDescriptor = pSecDescriptor; } #endif SafeWaitHandle mutexHandle = null; bool newMutex = false; RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(mutexHandle, false); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate(object userData) { // try block RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (initiallyOwned) { cleanupInfo.inCriticalRegion = true; Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); } } int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { errorCode = CreateMutexHandle(initiallyOwned, name, secAttrs, out mutexHandle); } if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name)); __Error.WinIOError(errorCode, name); } newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS; SetHandleInternal(mutexHandle); hasThreadAffinity = true; }, cleanupCode, cleanupInfo); createdNew = newMutex; } [PrePrepareMethod] private void MutexCleanupCode(Object userData, bool exceptionThrown) { MutexCleanupInfo cleanupInfo = (MutexCleanupInfo) userData; // If hasThreadAffinity isn’t true, we’ve thrown an exception in the above try, and we must free the mutex // on this OS thread before ending our thread affninity. if(!hasThreadAffinity) { if (cleanupInfo.mutexHandle != null && !cleanupInfo.mutexHandle.IsInvalid) { if( cleanupInfo.inCriticalRegion) { Win32Native.ReleaseMutex(cleanupInfo.mutexHandle); } cleanupInfo.mutexHandle.Dispose(); } if( cleanupInfo.inCriticalRegion) { Thread.EndCriticalRegion(); Thread.EndThreadAffinity(); } } } internal class MutexCleanupInfo { internal SafeWaitHandle mutexHandle; internal bool inCriticalRegion; internal MutexCleanupInfo(SafeWaitHandle mutexHandle, bool inCriticalRegion) { this.mutexHandle = mutexHandle; this.inCriticalRegion = inCriticalRegion; } } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public Mutex(bool initiallyOwned, String name) : this(initiallyOwned, name, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex(bool initiallyOwned) : this(initiallyOwned, null, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] public Mutex() : this(false, null, out dummyBool) { } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private Mutex(SafeWaitHandle handle) { SetHandleInternal(handle); hasThreadAffinity = true; } [SecurityPermissionAttribute(SecurityAction.LinkDemand,Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static Mutex OpenExisting(string name) { #if !FEATURE_PAL return OpenExisting(name, MutexRights.Modify | MutexRights.Synchronize); } [SecurityPermissionAttribute(SecurityAction.LinkDemand,Flags=SecurityPermissionFlag.UnmanagedCode)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static Mutex OpenExisting(string name, MutexRights rights) { #endif // !FEATURE_PAL if (name == null) { throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName")); } if(name.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); } if(System.IO.Path.MAX_PATH < name.Length) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong",name)); } // To allow users to view & edit the ACL's, call OpenMutex // with parameters to allow us to view & edit the ACL. This will // fail if we don't have permission to view or edit the ACL's. // If that happens, ask for less permissions. #if FEATURE_PAL SafeWaitHandle myHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); #else SafeWaitHandle myHandle = Win32Native.OpenMutex((int) rights, false, name); #endif int errorCode = 0; if (myHandle.IsInvalid) { errorCode = Marshal.GetLastWin32Error(); if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode) { throw new WaitHandleCannotBeOpenedException(); } if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name)); } // this is for passed through Win32Native Errors __Error.WinIOError(errorCode,name); } return new Mutex(myHandle); } // Note: To call ReleaseMutex, you must have an ACL granting you // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001). [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public void ReleaseMutex() { if (Win32Native.ReleaseMutex(safeWaitHandle)) { Thread.EndCriticalRegion(); Thread.EndThreadAffinity(); } else { throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException")); } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) { int errorCode; bool fAffinity = false; bool fHitRace = false; bool fRetry = false; while(true) { fHitRace = false; fRetry = false; mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name); errorCode = Marshal.GetLastWin32Error(); if( !mutexHandle.IsInvalid) { break; } if( errorCode == Win32Native.ERROR_ACCESS_DENIED) { // If a mutex with the name already exists, OS will try to open it with FullAccess. // It might fail if we don't have enough access. In that case, we try to open the mutex will modify and synchronize access. // RuntimeHelpers.PrepareConstrainedRegions(); try { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { Thread.BeginThreadAffinity(); fAffinity = true; } mutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); if(!mutexHandle.IsInvalid) { errorCode = Win32Native.ERROR_ALREADY_EXISTS; #if !FEATURE_PAL if (Environment.IsW2k3) { //Enables workaround for known OS bug at //http://support.microsoft.com/default.aspx?scid=kb;en-us;889318 //Workaround suggested by NeillC (The previous workaround of a acquiring a global mutex was not secure): //1)Open the mutex twice. //2)Call WaitForMultipleObjects with bWaitAll=TRUE and a zero timeout //3)If this call returns with ERROR_INVALID_PARAMETER then the two objects are the same and you can close one and use the other //4)If it returns timeout then you hit the ---- //5)If it returns success then you hit the ---- but you have to release before close. SafeWaitHandle tempMutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); if(!tempMutexHandle.IsInvalid) { RuntimeHelpers.PrepareConstrainedRegions(); try { uint originalRetCode = 0; IntPtr mutexPtr = mutexHandle.DangerousGetHandle(); IntPtr tempMutexPtr = tempMutexHandle.DangerousGetHandle(); IntPtr[] waitHandles = new IntPtr[] {mutexPtr, tempMutexPtr}; //We directly Pinvoke to WaitForMultipleObjects for two reasons: //1. The VM method WaitForMultiple does not support doing WaitForMultipleObjects // for COM STA threads. //2. We call the method in such a way that it's guaranteed to not block, so // it should not lead to any COM pumping/rentrancy issues. originalRetCode = Win32Native.WaitForMultipleObjects(2,waitHandles,true, 0); GC.KeepAlive(waitHandles); if(originalRetCode == WAIT_FAILED) { uint retCode = (uint) Marshal.GetLastWin32Error(); BCLDebug.Assert(retCode == Win32Native.ERROR_INVALID_PARAMETER, "Expected Invalid Parameter return code"); //Some weird transient error? if(retCode != Win32Native.ERROR_INVALID_PARAMETER) { mutexHandle.Dispose(); fRetry = true; } } else { fHitRace = true; if((originalRetCode >= WAIT_OBJECT_0) && (originalRetCode < (WAIT_OBJECT_0+2))) { Win32Native.ReleaseMutex(mutexHandle); Win32Native.ReleaseMutex(tempMutexHandle); } else if((originalRetCode >= WAIT_ABANDONED_0) && (originalRetCode < (WAIT_ABANDONED_0+2))) { Win32Native.ReleaseMutex(mutexHandle); Win32Native.ReleaseMutex(tempMutexHandle); } mutexHandle.Dispose(); } } finally { tempMutexHandle.Dispose(); } } else { mutexHandle.Dispose(); fRetry = true; } } #endif //!FEATURE_PAL } else { errorCode = Marshal.GetLastWin32Error(); } } finally { if (fAffinity) Thread.EndThreadAffinity(); } if(fHitRace || fRetry) continue; // There could be a ---- here, the other owner of the mutex can free the mutex, // We need to retry creation in that case. if( errorCode != Win32Native.ERROR_FILE_NOT_FOUND) { if( errorCode == Win32Native.ERROR_SUCCESS) { errorCode = Win32Native.ERROR_ALREADY_EXISTS; } break; } } else { break; } } return errorCode; } #if !FEATURE_PAL public MutexSecurity GetAccessControl() { return new MutexSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } public void SetAccessControl(MutexSecurity mutexSecurity) { if (mutexSecurity == null) throw new ArgumentNullException("mutexSecurity"); mutexSecurity.Persist(safeWaitHandle); } #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CapacityStreamGeometryContext.cs
- DynamicExpression.cs
- Visual3D.cs
- PropertyInformation.cs
- ConfigurationLocationCollection.cs
- SqlExpander.cs
- StylusCaptureWithinProperty.cs
- DialogResultConverter.cs
- BaseDataList.cs
- ComponentDispatcherThread.cs
- EntityTransaction.cs
- WeakRefEnumerator.cs
- XmlAttributeOverrides.cs
- NativeMethods.cs
- Compiler.cs
- StaticExtension.cs
- OleAutBinder.cs
- Brushes.cs
- DocumentPageHost.cs
- TimersDescriptionAttribute.cs
- FileDataSourceCache.cs
- Wow64ConfigurationLoader.cs
- GeneralTransform3D.cs
- PageRanges.cs
- MetadataUtil.cs
- ToolStripRenderEventArgs.cs
- FontResourceCache.cs
- XmlNodeComparer.cs
- FileNotFoundException.cs
- Panel.cs
- LineServices.cs
- ISFClipboardData.cs
- ToolStripGrip.cs
- TripleDESCryptoServiceProvider.cs
- SecurityTokenRequirement.cs
- BoundPropertyEntry.cs
- HttpInputStream.cs
- VBCodeProvider.cs
- ToolboxDataAttribute.cs
- ImageIndexConverter.cs
- HtmlInputReset.cs
- SoapAttributeAttribute.cs
- safelinkcollection.cs
- TypeCacheManager.cs
- ChineseLunisolarCalendar.cs
- ExpressionBuilderContext.cs
- WebConfigurationHost.cs
- MatrixAnimationUsingKeyFrames.cs
- CaseInsensitiveComparer.cs
- GPPOINT.cs
- TextElementEnumerator.cs
- TableDetailsRow.cs
- GridViewAutomationPeer.cs
- ConfigXmlCDataSection.cs
- TrustManagerPromptUI.cs
- Wildcard.cs
- PreviewKeyDownEventArgs.cs
- smtppermission.cs
- XsltException.cs
- FontFamily.cs
- InputLanguageEventArgs.cs
- AssociationType.cs
- SafeNativeMethodsMilCoreApi.cs
- ConditionalAttribute.cs
- RepeatInfo.cs
- RetrieveVirtualItemEventArgs.cs
- LightweightEntityWrapper.cs
- EntitySqlQueryState.cs
- ExpressionPrefixAttribute.cs
- OdbcParameter.cs
- HtmlPanelAdapter.cs
- Control.cs
- DoubleStorage.cs
- Message.cs
- Triangle.cs
- Globals.cs
- Console.cs
- TypeConverterValueSerializer.cs
- LinqDataView.cs
- MultiPartWriter.cs
- Memoizer.cs
- MetadataArtifactLoader.cs
- BindToObject.cs
- DispatcherProcessingDisabled.cs
- Point3DConverter.cs
- UnionQueryOperator.cs
- CatalogPartCollection.cs
- SystemIPAddressInformation.cs
- ExpressionReplacer.cs
- DataFormats.cs
- DynamicResourceExtensionConverter.cs
- FaultContractInfo.cs
- ConsumerConnectionPoint.cs
- HistoryEventArgs.cs
- LoginName.cs
- FormsAuthentication.cs
- PTManager.cs
- SamlAuthorizationDecisionClaimResource.cs
- CallbackDebugBehavior.cs
- QuadraticBezierSegment.cs