Random NullReferenceException crash in HealthMonitorLogger when retrying

Mar 8, 2012 at 2:33 PM

Since I've enabled automatic retries, I've sometimes get a NullReferenceException (ie a full application crash) with the following stack:


Microsoft.SilverlightMediaFramework.Plugins.Monitoring.HealthMonitorLogger.PopulateVideoEventLog(VideoEventLog log)
Microsoft.SilverlightMediaFramework.Plugins.Monitoring.SMFLogger.smfPlayer_RetryFailed(Object sender, EventArgs e)
Microsoft.SilverlightMediaFramework.Core.SMFPlayer.<RetryMonitor_RetryFailed>b__224(EventHandler i)
Microsoft.SilverlightMediaFramework.Utilities.Extensions.Extensions.IfNotNull[TItem](TItem item, Action`1 action)
Microsoft.SilverlightMediaFramework.Core.SMFPlayer.RetryMonitor_RetryFailed(RetryMonitor retryMonitor)
Microsoft.SilverlightMediaFramework.Core.RetryMonitor.<WaitTimer_Tick>b__b(Action`1 i)
Microsoft.SilverlightMediaFramework.Utilities.Extensions.Extensions.IfNotNull[TItem](TItem item, Action`1 action)
Microsoft.SilverlightMediaFramework.Core.RetryMonitor.WaitTimer_Tick(Object sender, EventArgs e)


(this was typed from a screenshot, mistakes may have found their way in)

This happens usually when I shutdown the SMFPlayer during the retry period. This is a common scenario for me as my app is Navigation based, with a Page holding the Player and another Page holding a list of videos.

Here is the method straight from the sources:

        /// Populates a video log with the basic video information. This is a superset of PopulateSimpleVideoLog
        public void PopulateVideoEventLog(VideoEventLog log)
            if (streamLoadedLog != null && streamLoadedLog != log)
                log.RelatedLogId = streamLoadedLog.LogId;
            log.VideoSessionId = healthMonitor.VideoSessionId;
            log.VideoSessionDuration = healthMonitor.VideoSessionRunningTime;

So looking here, only log and healthMonitor look suspect.


I guess during teardown, the timer is stopped too late, so it ticks and starts its things while the system state is unusable.

Mar 9, 2012 at 10:43 AM

Digging a bit there. Here is the Dispose() method from SMFPlayer:


public virtual void Dispose()
            CurrentPlaylistItem = null;



            if (_positionTimer.IsEnabled) _positionTimer.Stop();



I find it dangerous that there is a '_logger.Dispose()' before unloading the plugins, which can send log messages during their unloading. For instance, ProgressiveMediaPlugIn:


public void Unload()
                IsLoaded = false;
                PluginUnloaded.IfNotNull(i => i(this));
                SendLogEntry(KnownLogEntryTypes.ProgressiveMediaPluginUnloaded, message: ProgressiveMediaPluginResources.ProgressiveMediaPluginUnloadedLogMessage);
            catch (Exception ex)
                PluginUnloadFailed.IfNotNull(i => i(this, ex));

On the other hand, the _retryMonitor isn't disposed of in SMFPlayer.Dispose(), but in UnregisterMediaPlugin(...).


I will modify the SMFPlayer.Dispose() method in my local copy and see whether my crashes disappear.

Mar 9, 2012 at 4:51 PM

The Dispose() was a false trail. Found the real culprit/solution:

private void StopRetrying()
            if (_giveupTimer.IsEnabled)
            if (_successTimer.IsEnabled)
            // <--- begin add
            if (_waitTimer.IsEnabled)
            // end add --->

            IsRetrying = false;



PS: I'm quite fed up with CodePlex's editor not working 60% of the time for me (unable to insert code, unable to save edits, etc...).

Apr 25, 2012 at 2:28 PM

Even with the fix above, I still get the crash, but mostly in RetrySuccessful this time.

The repro is: play a DRM protected video, seek randomly, playback fails, retry kicks in, playback starts again, crash.