2013-09-05 36 views
6

Trong phần mềm máy chủ web của riêng tôi, tôi nhận được các mục trong Event Viewer trên máy chủ có chứa stack trace sau:Điều gì gây ra một NullReferenceException trong .NET Threading/chấp nhận kết nối TCP?

Framework Version: v4.0.30319 
Description: The process was terminated due to an unhandled exception. 
Exception Info: System.ArgumentNullException 
Stack: 
    at System.Net.FixedSizeReader.ReadCallback(System.IAsyncResult) 
    at System.Net.LazyAsyncResult.Complete(IntPtr) 
    at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
    at System.Net.ContextAwareResult.Complete(IntPtr) 
    at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) 
    at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) 

Không cần phải nói, này bị treo quá trình, có nghĩa là máy chủ đi xuống.

Vì không có stacktrace nào đề cập đến mã của riêng tôi, tôi khá bối rối. Đây có phải là lỗi trong .NET không? Nếu vậy, có cách giải quyết nào không? Hoặc là có một nguyên nhân được biết đến với ngoại lệ đặc biệt này?

Tên CompletionPortCallback được đề cập trong ngăn xếp dẫn tôi tin rằng nó xảy ra khi máy chủ cố gắng chấp nhận kết nối TCP đến, vì vậy tôi sẽ bao gồm mã có liên quan cho điều đó bên dưới. Tất nhiên tôi rất vui khi bao gồm mã khác nếu bạn cho rằng vấn đề nằm ở nơi khác.

Các cuộc gọi đến BeginAccept trông như thế này:

Ở đây, _listeningSocket là loại System.Net.Sockets.Socket.

Phương thức acceptSocket được hiển thị bên dưới. Tôi sẽ giả định rằng các ý kiến ​​giải thích mã cũng đủ; nếu không, tôi vui lòng làm rõ trong một bình luận. Vì mã này chạy trong chế độ RELEASE trên máy chủ trực tiếp, tất nhiên, #if DEBUG sẽ là sai.

private void acceptSocket(IAsyncResult result) 
{ 
#if DEBUG 
    // Workaround for bug in .NET 4.0 and 4.5: 
    // https://connect.microsoft.com/VisualStudio/feedback/details/535917 
    new Thread(() => 
#endif 
    { 
     // Ensure that this callback is really due to a new connection (might be due to listening socket closure) 
     if (!IsListening) 
      return; 

     // Get the socket 
     Socket socket = null; 
     try { socket = _listeningSocket.EndAccept(result); } 
     catch (SocketException) { } // can happen if the remote party has closed the socket while it was waiting for us to accept 
     catch (ObjectDisposedException) { } 
     catch (NullReferenceException) { if (_listeningSocket != null) throw; } // can happen if StopListening is called at precisely the "wrong" time 

     // Schedule the next socket accept 
     if (_listeningSocket != null) 
      try { _listeningSocket.BeginAccept(acceptSocket, null); } 
      catch (NullReferenceException) { if (_listeningSocket != null) throw; } // can happen if StopListening is called at precisely the "wrong" time 

     // Handle this connection 
     if (socket != null) 
      HandleConnection(socket); 
    } 
#if DEBUG 
    ).Start(); 
#endif 
} 
+0

Theo như tôi biết bạn nên vượt qua '_listeningSocket' trong lệnh' BeginAccept() 'thay vì null:' _listeningSocket.BeginAccept (acceptSocket, _listeningSocket); 'xem tài liệu và ví dụ. Đó là lý do tại sao bạn nhận được ngoại lệ ArgumentNull. –

+0

Đây rõ ràng là một lỗi trong khuôn khổ .NET. Nếu bạn đã msiused API lỗi sẽ xảy ra ngay sau đó, không sâu trong ruột của BCL trên một cuộc gọi lại IO. Câu hỏi bây giờ là làm thế nào để làm việc xung quanh nó. – usr

Trả lời

-1

Tôi nghĩ ngoại lệ này được ném vì bạn chuyển tham chiếu null làm tham số thứ hai.

Từ MSDN Socket.BeginAccept Documentation (http://msdn.microsoft.com/de-de/library/5bb431f9.aspx):

Bạn phải tạo ra một phương pháp gọi lại mà thực hiện các đại biểu AsyncCallback và vượt qua tên của nó với phương pháp BeginAccept. Để làm điều này, ở mức tối thiểu, bạn phải truyền đối tượng Socket đang nghe đến BeginAccept thông qua tham số trạng thái. Nếu cuộc gọi lại của bạn cần thêm thông tin, bạn có thể tạo một lớp nhỏ để giữ Ổ cắm và các thông tin cần thiết khác. Chuyển một thể hiện của lớp này đến phương thức BeginAccept thông qua tham số trạng thái.

+0

Đây không phải là nó. Nó không quan tâm đến tham số * state *. Nó chỉ lưu trữ nó không bị thay đổi trong đối tượng 'IAsyncResult', nơi bạn có thể lấy nó trong callback. Nó có thể là 'null' tốt và điều này luôn làm việc cho tôi. – Timwi

4

Câu trả lời đơn giản vì nó gây thất vọng.

Nó chỉ ra rằng ArgumentNullException thực sự được ném bởi mã của riêng tôi, được thực hiện trong cuộc gọi lại đến cuộc gọi không đồng bộ và phải là trong theo dõi ngăn xếp. Tôi tin tưởng dấu vết ngăn xếp quá nhiều; thực tế là điều này đã không hiển thị trong ngăn xếp dấu vết dẫn tôi vào một ca khúc sai trong một thời gian dài.

Khi nhà phát triển C# biết, tuyên bố throw; (không phải throw e;) là nghĩa vụ phải giữ theo dõi ngăn xếp ngoại lệ không thay đổi gì. System.Net.FixedSizeReader.ReadCallback bắt và giữ lại ngoại lệ thông qua tuyên bố throw; như vậy, nhưng dấu vết ngăn xếp được hiển thị trong Trình xem sự kiện đã bị cắt bớt. Tôi chỉ có thể phỏng đoán rằng đây là lỗi trong CLR hoặc Trình xem sự kiện hoặc một số tương tác giữa hai người, chỉ làm cho một phần của dấu vết ngăn xếp từ hướng dẫn throw; trở đi hiển thị.

Khi tôi chạy phần mềm trên bảng điều khiển thay vì dịch vụ, tôi nên nghĩ sớm hơn nhiều, dấu vết ngăn xếp đầy đủ của ngoại lệ được hiển thị trên bảng điều khiển, cho biết nguyên nhân thực sự của ngoại lệ là của riêng tôi mã.

+0

cảm ơn bạn đã trả lời câu hỏi của riêng bạn, gợi ý của bạn rằng stacktrace đã bị cắt ngắn và chạy nó như một giao diện điều khiển đã giúp tôi rất nhiều. Trong trường hợp của tôi, tôi đã mong đợi WebException.response của tôi được lấp đầy nơi nó không được -> nullreference -> thổi dịch vụ nservicebus của tôi ra khỏi nước mà không có bất kỳ lỗi nào –

0

Dựa trên https://connect.microsoft.com/VisualStudio/feedback/details/535917 và trải nghiệm của riêng tôi, đây có thể là ngoại lệ knock-on từ một vấn đề khác trước đó.

Thử thêm trình xử lý ngoại lệ toàn cục và ghi & xóa tất cả các ngoại lệ ra đĩa, sau đó kiểm tra tệp nhật ký sau sự cố để tìm nguyên nhân thực sự.

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