簡體   English   中英

Mutex構造函數上的這個OutOfMemoryException的原因是什么?

[英]What is the cause of this OutOfMemoryException on Mutex constructor?

我在這行代碼上得到一個System.OutOfMemoryException

mutex2 = new Mutex(true, "Name2");

這是堆棧跟蹤:

{"Exception of type 'System.OutOfMemoryException' was thrown."}
   at Microsoft.Win32.Win32Native.CreateMutex(SECURITY_ATTRIBUTES lpSecurityAttributes, Boolean initialOwner, String name)
   at System.Threading.Mutex.CreateMutexHandle(Boolean initiallyOwned, String name, SECURITY_ATTRIBUTES securityAttribute, SafeWaitHandle& mutexHandle)
   at System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.Mutex.CreateMutexWithGuaranteedCleanup(Boolean initiallyOwned, String name, Boolean& createdNew, SECURITY_ATTRIBUTES secAttrs)
   at System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew, MutexSecurity mutexSecurity)
   at System.Threading.Mutex..ctor(Boolean initiallyOwned, String name)
   at Foo.FooDefinitions.FooManager.FooForm.FooForm_Load(Object sender, EventArgs e) in c:\tfs\DWS\TRUNK\DEV\FooDefinitions\FooManager\FooForm.cs:line 92

它只會在我使用模仿時發生。 沒有模擬(在我的普通Windows帳戶上運行)它將運行正常。 模仿是這樣的:

    if (!NativeMethods.LogonUser(userName, domainName, password, 2, 0, ref this._tokenHandle)) // [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }
    this._impersonatedUser = new WindowsIdentity(this._tokenHandle).Impersonate();

編輯 :只是為了闡述,我正在創建遺留代碼的自動化測試。 如果可以的話,我會刪除互斥鎖的使用。 我目前正在調查Mutex構造函數上的SecurityCriticalAttribute

EDIT2 :以下是代碼的完整示例:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;

namespace ReinierDG.MutexTesting
{
    [TestClass]
    public class MutexTest
    {
        [TestMethod]
        public void CreateMutexUnderImpersonation()
        {
            var credentials = new NetworkCredential("testagent", "secretpassword");
            var tokenHandle = new IntPtr();
            if (!NativeMethods.LogonUser(credentials.UserName, credentials.Domain, credentials.Password, 2, 0, ref tokenHandle))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            var impersonatedUser = new WindowsIdentity(tokenHandle).Impersonate();
            // this will run indefinately or untill memory is full with 1 cpu core at 100%
            var mutex = new Mutex(true, "test");
        }

        internal static class NativeMethods
        {
            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            internal static extern bool LogonUser([MarshalAs(UnmanagedType.LPWStr)]string lpszUsername, [MarshalAs(UnmanagedType.LPWStr)]string lpszDomain, [MarshalAs(UnmanagedType.LPWStr)]string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
        }
    }
}
    // this will run indefinately or untill memory is full

那么,那將是一個解釋。 我們必須假設注釋與代碼不匹配。 這里最明顯的問題是您沒有發布與錯誤相關的堆棧跟蹤,並且無法幫助您診斷基礎問題。 我只能發布提示,讓你進入下一階段。

很容易假設CreateMutex()失敗了。 但事實並非如此,winapi函數的失敗報告的方式不同,你會在堆棧跟蹤中看到__Error.WinIOError() 並且錯誤代碼會有所不同,您將收到錯誤1450,ERROR_NO_SYSTEM_RESOURCES,“系統資源不足以完成所請求的服務”。

事實上,CLR拋出異常。 或者換句話說,它是pinvoke marshaller失敗了。 這使得診斷變得非常復雜,在可以拋出OOM的大量代碼中存在大量的地方。 它經常需要分配非托管內存以完成pinvoke工作,如果失敗則會得到OOM-kaboom。 可能發生的許多方法,內部非托管堆損壞當然就足夠了。 你的LogonUser()pinvoke聲明在技術上是錯誤的(CharSet.Auto!= UnmanagedType.LPWStr),但沒有錯誤解釋這個問題。

您需要更接近異常的根,並且需要啟用非托管調試器。 對於VS2015,請使用“項目”>“屬性”>“調試”選項卡>勾選“啟用本機代碼調試”復選框。 您需要調試CLR的符號才能理解堆棧跟蹤。 使用工具>選項>調試>符號>勾選“Microsoft Symbol Server”。 您需要使調試器在第一次機會異常時停止,使用Debug> Windows> Exception Settings>勾選“Win32 Exceptions”。

你現在會知道更多,你可以在你的問題中發布更好的堆棧跟蹤。 盡管如此,這可能會給SO用戶或您提供清晰的診斷信息,以顯示如何通過冒充來解釋這一不幸事件的可能性很小。 在Microsoft支持的幫助下進行調用是明智的,但他們需要更多地了解該“testagent”帳戶的配置方式。 請記住,此類帳戶通常會被故意削弱,以確保單元測試不會需要太多系統資源。

您可以使用LOGON32_LOGON_NEW_CREDENTIALS(9)作為LogonType和LOGON32_PROVIDER_WINNT50(3)作為LogonProvider,它將成功。 我認為這是關於權威的

當你在代碼中調試它時,你可以在無限循環中找到它, mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name); ERROR_ACCESS_DENIED失敗。 它將運行Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); ,但它也失敗了ERROR_FILE_NOT_FOUND

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM