3 votes

Exception de référence nulle dans la journalisation des exceptions masquant une véritable erreur

Nous avons un processus long qui est initié par une requête web. Afin de donner au processus le temps de se terminer, nous le faisons tourner sur un nouveau thread et utilisons un Mutex pour nous assurer qu'une seule instance du processus peut s'exécuter. Ce code fonctionne comme prévu dans nos environnements de développement et de test, mais échoue dans notre environnement de production avec une exception de référence nulle. Le journal de l'application n'enregistre rien et nos responsables des opérations signalent que le pool d'applications se bloque. (Il semblerait que ce soit un problème d'environnement, mais nous devons partir du principe que les environnements sont configurés de manière identique). Jusqu'à présent, nous n'avons pas été en mesure de déterminer où se trouve la référence nulle.

Voici l'exception du journal des événements de l'application :

Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
StackTrace:    at Jobs.LongRunningJob.DoWork()
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Et voici le code (légèrement aseptisé) :

public class LongRunningJob: Job
{
    private static Mutex mutex = new Mutex();

    protected override void PerformRunJob()
    {
        var ts = new ThreadStart(LongRunningJob.DoWork);
        var thd = new Thread(ts);
        thd.IsBackground = true;
        thd.Start();
    }

    private static void DoWork()
    {
        var commandTimeOut = 180;

        var from = DateTime.Now.AddHours(-24);
        var to = DateTime.Now;

        if (mutex.WaitOne(TimeSpan.Zero))
        {
            try
            {
               DoSomethingExternal(); // from what we can tell, this is never called
            }
            catch (SqlException sqlEx)
            {
                if (sqlEx.InnerException.Message.Contains("timeout period elapsed"))
                {
                    Logging.LogException(String.Format("Command timeout in LongRunningJob: CommandTimeout: {0}", commandTimeOut), sqlEx);
                }
                else
                {
                    Logging.LogException(String.Format("SQL exception in LongRunningJob: {0}", sqlEx.InnerException.Message), sqlEx);
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(String.Format("Error processing data in LongRunningJob: {0}", ex.InnerException.Message), ex);
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        else
        {
            Logging.LogMessage("LongRunningJob is already running.");
        }
    }
}

4voto

usr Points 74796

Afin de trouver un NullReferenceException vous examinez en fait chaque opération de déréférencement. Je ne vois que l'opération suspecte suivante :

ex.InnerException.Message

Vous ne pouvez pas supposer ex.InnerException n'est pas nulle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X