2016-04-13 26 views
5

Trong khi thử nghiệm một ứng dụng, tôi đã chạy vào một hành vi lạ. Một số thử nghiệm sử dụng mạo danh để chạy mã với tư cách người dùng khác, nhưng họ sẽ luôn treo, không bao giờ hoàn thành.Tạo Mutex bị treo trong khi sử dụng mạo danh

Sau khi điều tra, vấn đề đã được thu hẹp lại khi sử dụng mutexes. Ban đầu, chúng tôi đã sử dụng mã mạo danh của riêng mình dựa trên MSDN documentation, nhưng ngay cả khi sử dụng SimpleImpersonation library sự cố vẫn còn. Dưới đây là một ví dụ nhỏ để tạo lại vấn đề:

using (Impersonation.LogonUser(DOMAIN, USER, PASSWORD, LogonType.Interactive)) 
{ 
    Console.WriteLine("Impersonated"); 
    bool mine; 
    using (new Mutex(true, "Mutex", out mine)) 
    { 
     if (!mine) 
      throw new Exception("Couldn't get mutex"); 
     Console.WriteLine("Got mutex"); 
    } 
} 

Console.WriteLine("Finished"); 

này không bao giờ kết thúc, nó bị kẹt trên phù hợp với việc tạo ra mutex. Các documentation nói rằng nó hoặc là nên ném một ngoại lệ hoặc trả lại một cái gì đó, nhưng không đề cập đến chặn.

Một số quan sát khác, mà có thể hoặc không có thể liên quan:

  • nếu chúng ta "mạo danh" người sử dụng hiện tại, nó sẽ trả về ngay lập tức
  • nếu chúng ta chạy các ứng dụng thực tế và bắt đầu dụ khác như một người dùng khác, mọi thứ hoạt động như dự định

Có thể có điều gì đó đang xảy ra với tài nguyên hệ thống cơ bản, nhưng chúng tôi không thể tìm ra. Làm thế nào để thực hiện công việc này?

CẬP NHẬT: Theo nhận xét của Hans, tôi đã thử vô hiệu hóa Windows Defender, nó không giúp ích gì. Dưới đây là một stacktrace của nơi mà nó treo:

[email protected]() 
    [email protected]() 
    mscorlib.ni.dll!719c1867() 
    [Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack] 
    mscorlib.ni.dll!719c1852() 
    [Managed to Native Transition] 
    mscorlib.dll!System.Threading.Mutex.CreateMutexHandle(bool initiallyOwned, string name, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES securityAttribute, out Microsoft.Win32.SafeHandles.SafeWaitHandle mutexHandle) 
     mscorlib.dll!System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(object userData) 
    [Native to Managed Transition] 
    [Managed to Native Transition] 
    mscorlib.dll!System.Threading.Mutex.CreateMutexWithGuaranteedCleanup(bool initiallyOwned, string name, out bool createdNew, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs) 
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew, System.Security.AccessControl.MutexSecurity mutexSecurity) 
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew)  
    MutexImpersonationTest.exe!MutexImpersonationTest.Program.Main(string[] args) Line 16 
+0

Rất lạ. FWIW, nếu bạn không nhận được câu trả lời hay, giải pháp cuối cùng sẽ là quên các lớp .net và sử dụng P/Invoke để gọi trực tiếp Win32 API. –

Trả lời

6

Dường như mã để có được một Mutex đang bị mắc kẹt trong một vòng lặp vô hạn, và trong các thử nghiệm của tôi, nó pegging một lõi ở mức 100% trong cuộc gọi đến new Mutex(...).

Lý do cho điều này có vẻ là mã khung đầu tiên cố gắng gọi Win32 CreateMutex, nếu không thành công với lỗi "Truy cập bị từ chối", hãy thử gọi số OpenMutex thay thế. Nếu cuộc gọi OpenMutex không thành công với một lỗi cho biết mutex không tồn tại, nó lặp lại toàn bộ quá trình một lần nữa, và do đó bị mắc kẹt trong một vòng lặp vô hạn nếu mutex không tồn tại.

Theo CreateMutex documentation, điều này về cơ bản là cách tiếp cận đúng, nhưng dường như không chiếm trường hợp khi ban đầu CreateMutex không thành công với một Access Denied đó là không do quyền trên một mutex hiện có.

Một điều dường như hoạt động khi tôi thử nó là tiền tố tên mutex với "Global \", hy vọng đây là giải pháp thích hợp cho bạn.

+0

Các mutex toàn cầu có thể được tạo ra như thế này, nhưng điều đó giới hạn các phiên bản trên tất cả các phiên người dùng, đó là một thay đổi đáng kể trong hành vi ... –

+0

Bắt tốt, mã (đúng) trong thời gian [ở đây] (http: // referencesource. microsoft.com/#mscorlib/system/threading/mutex.cs.9faa5b5e2b4c8f31). –

+1

@ MártonMolnár Nếu bạn muốn một mutex phiên cụ thể, bạn có thể có một vài tùy chọn - bạn có thể tạo mutex * trước * mạo danh và đặt quyền trên đó để cho phép người dùng mạo danh truy cập hoặc sử dụng " Tiền tố toàn cầu \ ", nhưng kết hợp ID phiên (' Quy trình.GetCurrentProcess(). SessionId') vào tên của mutex, do đó tạo ra một mutex "mỗi phiên" trong không gian tên chung. – Iridium

Các vấn đề liên quan