Race condition between TimeSyncController/ManifestUpdater
Created by: Gontran-Molotov
Observed behavior
When playing a live stream, a race condition may occur between TimeSyncController and ManifestUpdater. Every time a new manifest is downloaded, TimeSyncController sends a request to the time servers. Simultaneouly, ManifestUpdater starts a timer with the value of minimumUpdatePeriod
as delay. This timer will call onRefreshTimer() to download the next manifest, only if the current manifest processing is over.
The current manifest processing is considered as finished by ManifestUpdater once the STREAMS_COMPOSED event is emitted, but this event won't be emitted as long as a response from the time servers has not been received. It this takes a long time, the timer of ManifestUpdater will be triggered before the processing of the current manifest is finished and the next manifest won't be downloaded. This breaks the loading of next manifests, and so the loading of next audio/video segments. The video player will be infinitely in a stalled state without possibility to recover.
Steps to reproduce
The race condition can be simulated by delaying the trigger of the TIME_SYNCHRONIZATION_COMPLETED event in the TimeSyncController.completeTimeSyncSequence()
method:
function completeTimeSyncSequence(failed, time, offset) {
setIsSynchronizing(false);
setTimeout(
() => eventBus.trigger(Events.TIME_SYNCHRONIZATION_COMPLETED, { time: time, offset: offset, error: failed ? new DashJSError(TIME_SYNC_FAILED_ERROR_CODE) : null }),
5000
);
}
In this example, the event triggering is delayed by 5 seconds. This value must be chosen so that it is greater than the value of minimumUpdatePeriod
in the manifest files.