2016-08-08 18 views
4

:ここMutexコンストラクタでこのOutOfMemoryExceptionが発生する原因は何ですか?私はこのコード行に<code>System.OutOfMemoryException</code>を取得しています

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(); 

EDIT::ただ、eloborateする私は、レガシーコードの自動テストを作成してい偽装は、このようなものです。もしできれば、私はミューテックスの使用を取り除きました。私は現在、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); 
     } 
    } 
} 
+4

で失敗しました[ここ](http://referencesource.microsoft.com/#mscorlib/system/threading/mutex.cs,434)源です。 'while(true)'の中に 'CreateMutex'を表示します。おそらくあなたは無限ループのバグを発見したでしょうか? – Quantic

+2

あなたの 'FooForm.FooForm_Load'メソッドのコード – giammin

+0

しかし、まず:あなたはミューテックスが必要ですか?フォームのロードイベントで??? – giammin

答えて

7
// this will run indefinately or untill memory is full 

まあ、1つの説明のようになります。ここでは、コードの完全な例です。コメントはコードと一致しないと仮定しなければなりません。ここで最も明白な問題は、エラーに十分関連するスタックトレースを投稿しておらず、根本的な問題を診断するのに役立たないということです。私はあなたを次のステージに導くヒントを投稿するだけです。

は、失敗したCreateMutex()であると仮定することはあまりにも簡単です。しかし、そうではない場合、winapi関数の失敗は異なって報告されます。スタックトレースには__Error.WinIOError()が戻っています。そして、エラーコードが違うと、エラー1450、ERROR_NO_SYSTEM_RESOURCES、 "不足しているシステムリソースが要求されたサービスを完了するために存在する"が表示されます。

それは実際には例外をスローCLRです。換言すれば、それが失敗したのPInvokeマーシャラーです。それは診断をかなり複雑にします.OOMを投げることができる非常に大量のコードの中に非常に多くの場所があります。 pinvokeジョブを完了させるために管理されていないメモリを割り当てる必要があります。失敗した場合は、OOM-kaboomを取得します。起こりうる多くの方法、内部の管理されていないヒープの破損は確かに十分です。あなたのLogonUser()のPInvoke宣言は、この問題を説明するのに十分な間違った(CharSet.Auto!= UnmanagedType.LPWStr)技術的に間違っている、しかし、ではありません。

あなたは例外のルートに近づくとそれが管理されていないデバッガを有効にする必要が取得する必要があります。 VS2015の場合は、Project> Properties> Debuggingタブを選択し、 "Enable native code debugging"チェックボックスを選択します。スタックトレースを理解するためには、CLRのデバッグシンボルが必要です。 [ツール]> [オプション]> [デバッグ]> [シンボル]> [Microsoft Symbol Server]を選択します。 Debug> Windows> Exception Settings> tick "Win32 Exceptions"を使用して、最初の例外でデバッガを停止させる必要があります。

あなたは、あなたの質問にはるかに優れたスタックトレースを投稿することができ、より多くの今多くのことを知っていますよ。それでも、この事故がどうやって偽装によって説明されるかを示すクリスタルクリアな診断を、SOのユーザーまたはあなたに与えることは間違いありません。マイクロソフトサポートの助けを借りて呼び出すことは賢明かもしれませんが、その "テストエージェント"アカウントがどのように構成されているかを正確に知る必要があります。単体テストではあまりにも多くのシステムリソースを要求できないように、このようなアカウントは意図的に障害があることに注意してください。

1

LogonTypeとしてLOGON32_LOGON_NEW_CREDENTIALS(9)を使用し、LogonProviderとしてLOGON32_PROVIDER_WINNT50(3)を使用すると、正常に実行されます。私はそれがauthorityについてだと思います。

はあなたのコードでそれをデバッグする場合、あなたは無限loopでそれを見つけることができ、mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name);ERROR_ACCESS_DENIEDで失敗しました。それはWin32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);を実行しますが、それはまたERROR_FILE_NOT_FOUND

関連する問題