[Live-devel] live555 event trigger behaviour

Döring Dr. Matthias matthias.doering at geutebrueck.com
Thu Jun 14 09:28:02 PDT 2012


Hello Ross,
because I am new here let me first express my thankfulness for that great library which will probably save a huge amount of development time for the project I am about to evaluate currently.
I read your FAQ and the mailing lists multiple times to not bother you with trivial questions. Nevertheless I came now to a vulnerability in the design in the event trigger approach where I would like to ask you for your opinion.
The general statement for triggering the Live555 event loop from external devices is:
“TriggerEvent is the only Live555 function that you’re permitted to call from a non LIVE555 thread”
In my opinion the event trigger approach is not thread safe and causes thread racing effects of different severity depending on the usage scenario. To illustrate that a rough description of my destination.

-          Multiple sources (based on the DeviceSource sample) with different codecs (MJPEG, H264, MPEG-2) are to create triggers for Live555 based on the triggerEvent procedure. The source streams are live video from different hardware grabbers. The source implementations work already quite well.

-          Each source has registered its individual event trigger.

-          Each source runs in its own thread which produces a trigger when a frame is available

-          The result is that multiple producer threads have simultaneous write access to the 4 following global live555 variables and one consumer thread (live555) has read access. The critical shared variables are:  fTriggeredEventClientDatas, fLastUsedTriggerMask, fLastUsedTriggerNum and fTriggersAwaitHandling.

-          Because the access to the shared variables is not protected with locks one gets racing conditions which may even lead to a crash of the application because of access violations (what happened in my tests).
For example let’s assume we have an JPEG source class and an H264 source class – for simpliciy just one instance of each. They call the trigger Event function simultaneously:

void CGscTaskScheduler::triggerEvent(EventTriggerId eventTriggerId, void * clientData)
{
       if (eventTriggerId == fLastUsedTriggerMask)
       {

>> Thread 1: JPEG source runs that code
=======================================

              fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
       }
       else
       {
             EventTriggerId mask = 0x80000000;
             for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i)
             {
                    if ((eventTriggerId&mask) != 0)
                    {
                           fTriggeredEventClientDatas[i] = clientData;
                           fLastUsedTriggerMask = mask;

>> Thread 2: H264 source runs that code
=======================================

                           fLastUsedTriggerNum = i;
                    }
                    mask >>= 1;
             }
       }
       fTriggersAwaitingHandling |= eventTriggerId;
}

If thread 2 changes the value of the fLastUsedTriggerNum shared variable before thread 1 wrote its clientData then the source pointer is written to the wrong index in the ClientDatas array. One result could be that the callback deliverFrame0 of the JPEG source gets a pointer to a H264 source instance (and vice versa). That produces undefined behaviour and will normally cause an access violation. There are other racing effects imaginable (lost frames, frames are written to a wrong RTP channel). Such effects may happen in all code parts which have access to the shared variables (for example the live555 SingleStep procedure modifies these values as well which could lead to race effects with the source threads).
My only solution without modifying the live555 sources to solve that problem was to implement my own TaskScheduler which is derived from BasicTaskScheduler and which overwrites the 4 virtual functions triggerEvent, createEventTrigger, deleteEventTrigger, SingleStep. The only change in the reimplemented virtual functions of the base classes was the introduction of a mutex which synchronizes the simultaneous accesses for the critical code parts. With that I got rid of the different racing effects I had before.
Do I see anything wrong or did I misunderstand the design basics of the Event trigger mechanism? I appreciate the general intention to have platform independent code. But in favor of the plagued Windows users which want to stream live sources could you please consider to introduce some conditional define based thread Windows synchronization in the task scheduler event trigger mechanism to avoid the described problems? Without that I do not see a way to use the event trigger mechanism in a reliable way.

Best regards
Matthias

GEUTEBRÜCK GmbH         Tel:    +49 2645 137-680
Im Nassen 7-9   Mobil:
53578 Windhagen Fax:    +49 2645 137-999
http://www.geutebrueck.de       E-Mail:         matthias.doering at geutebrueck.com<mailto:matthias.doering at geutebrueck.com>
Geschäftsführer: Katharina Geutebrück, Christoph Hoffmann; UST-Ident-Nr.: DE813443473; Handelsregister: HRB 14475 Montabaur
[cid:topline_geu_logo.jpg]<http://www.geutebrueck.com/>


Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.

This e-mail contains confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorised copying, disclosure or distribution of the material in this e-mail is strictly forbidden.

Weder die GEUTEBRÜCK GmbH noch der Absender (Matthias Döring) übernehmen die Haftung für Viren; es obliegt Ihrer Verantwortung, die E-Mail und deren Anhänge auf Viren zu prüfen.
Anhänge:

Versand am 14.06.2012 18:28 von Döring Matthias


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20120614/1552e5b5/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: topline_geu_logo.jpg
Type: application/octet-stream
Size: 6449 bytes
Desc: topline_geu_logo.jpg
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20120614/1552e5b5/attachment-0001.obj>


More information about the live-devel mailing list