2013-09-05 23 views
6

は、私は、次のスタックトレースが含まれているサーバー上のイベントビューアのエントリを取得しています:.NETでNullReferenceExceptionが発生する理由は何ですか?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*) 

言うまでもないが言って、これは、サーバーがダウンしたことのプロセスを、クラッシュします。

stacktraceには自分のコードが記述されていないので、私は非常に困惑しています。これは.NETのバグですか?その場合は、既知の回避策がありますか?または、この特定の例外には既知の原因がありますか?

stacktraceに記載されているCompletionPortCallbackという名前は、サーバーが受信TCP接続を受け入れるときに発生すると考えているため、以下では関連するコードを含めます。もちろん、問題が他の場所にあると思うなら、他のコードも含めることができます。

ここで、_listeningSocketはタイプSystem.Net.Sockets.Socketは次のとおりです。

BeginAcceptへの呼び出しは次のようになります。

acceptSocketの方法を以下に示します。コメントがコードを十分に説明していると仮定します。もしそうでなければ、私はコメントで明確にすることができてうれしいです。このコードはライブサーバーでRELEASEモードで実行されるため、#if DEBUGは当然間違いです。

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

私の知る限り、nullの代わりに 'BeginAccept()'呼び出しで '_listeningSocket'を渡すべきです。' _listeningSocket.BeginAccept(acceptSocket、_listeningSocket); 'ドキュメントと例を参照してください。そのため、あなたはArgumentNull例外を受け取りました。 –

+0

これは明らかに.NETフレームワークのバグです。 APIをmsiusしていた場合は、IOコールバックのBCLの奥深くではなく、エラーが発生したはずです。問題は、これを回避する方法です。 – usr

答えて

-1

2番目のパラメータとしてnull参照を渡すため、この例外がスローされると思います。あなたはAsyncCallbackデリゲートを実装するコールバックメソッドを作成し、BeginAcceptメソッドにその名を渡す必要があります

:MSDN Socket.BeginAcceptドキュメント(http://msdn.microsoft.com/de-de/library/5bb431f9.aspx)から

。これを行うには、最低限、listenするSocketオブジェクトをstateパラメータを介してBeginAcceptに渡す必要があります。コールバックがより多くの情報を必要とする場合は、Socketと他の必要な情報を保持する小さなクラスを作成できます。このクラスのインスタンスを、stateパラメータを介してBeginAcceptメソッドに渡します。

+0

これはそうではありません。 * state *パラメータはまったく気にしません。 'IAsyncResult'オブジェクトにそのまま変更を保存するだけで、コールバックでそれを取得できます。それは 'null'でもいいですが、これはいつも私のために働いています。 – Timwi

4

答えはそれほど簡単ではありません。

ArgumentNullExceptionは実際に私自身のコードによって非同期呼び出しのコールバックで実行され、はスタックトレースのであったはずです。私はスタックトレースをあまりにも信頼しました。これがスタックトレースに表示されなかったという事実が私を長い間間違った軌道に導いてくれました。

C#開発者が知っているように、throw;ステートメント(throw e;ではなく)は、例外スタックトレースを変更しない状態に保つことになっています。 System.Net.FixedSizeReader.ReadCallbackは、このようなthrow;ステートメントを介してキャッチして例外を戻しますが、イベントビューアに表示されるスタックトレースは切り捨てられます。私は、これがCLRまたはイベントビューアのバグ、または2つの間の相互作用によって、throw;命令以降のスタックトレースの一部のみを表示させると推測することができます。

サービスとしてではなく、コンソールでソフトウェアを実行したときに、はるかに早く考えていたはずの例外の完全なスタックトレースがコンソールに表示され、例外の真の原因が自分自身であることが示されましたコード。

+0

あなた自身の質問に答えてくれてありがとう、スタックトレースが切り捨てられ、コンソールとして実行するという提案は私を助けてくれました。私の場合、私はWebException.responseが満たされていないことを期待していました - > nullreference - >エラーなしでnservicebusサービスを水中から吹き飛ばしました –

0

https://connect.microsoft.com/VisualStudio/feedback/details/535917と自分の経験に基づいて、これは以前の別の問題のノックオン例外である可能性があります。

グローバル例外ハンドラを追加し、&すべての例外をディスクにフラッシュしてから、クラッシュ後にログファイルをチェックして実際の原因を調べてください。

関連する問題