[Live-devel] [EXTERNAL] Re: Possible concurrency issue with triggerEvent()

Hansen Jan Rørgård jan.r.hansen at dk.saabgroup.com
Wed Jun 7 05:52:13 PDT 2023


Hi,

Here is more information about the issue and an attached test program that is able to reproduce the issue(s).

First let's define:
LT : LIVE555 thread
NT : non-LIVE555 thread
EH1 : EventHandler1
EH2 : EventHandler2
TAW : fTriggersAwaitingHandling

triggerEvent called but eventHandler is not:
====================================
Let's say NT has called createEventTrigger two times with EH1 and EH2 and now has:
ET1 : EventTriggerId1
ET2 : EventTriggerId2
Then we can have the sequence:
NT                                                     LT
|                                                        |
triggerEvent(ET1) ----------------> (TAW=0x00000001)
                                                           ---------------
                                                                             | singleStep()
                                                                             | read TAW into register (reg=0x00000001)
                                                                             | clear bit corresponding to ET1 in register (reg=0x00000000)
triggerEvent(ET2) ----------------> (TAW=0x00000003)
                                                                             | write register into TAW (TAW=0x00000000)
                                                           ---------------
                                                          |

In this sequence ET2 is set by NT but LT does not see it due to a race condition, which means that ET2 will not be handled

triggerEvent called and eventHandler is called twice:
===========================================
Let's say NT has called createEventTrigger two times with EH1 and EH2 and now has:
ET1 : EventTriggerId1
ET2 : EventTriggerId2
Then we can have the sequence:
NT                                                     LT
|                                                        |
triggerEvent(ET1) ----------------> (TAW=0x00000001)
                                                           ---------------
                                                                             | singleStep()
                                                                             | read TAW into register (reg=0x00000001)
                                                                             | clear bit corresponding to ET1 in register (reg=0x00000000)
triggerEvent(ET2) ---------------->
               | read TAW into register (reg=0x00000001)
               | set bit corresponding to ET2 in register (reg=0x00000003)
                                                                             | write register into TAW (TAW=0x00000000)
               | write register into TAW (TAW=0x00000003)

In this sequence, when ET2 is set by NT the TAW register ends up indicating that ET1 is triggered even if it has just been handled by LT

triggerEvent called twice but eventHandler is called once:
===============================================
Let's say NT has called createEventTrigger with EH1 and now has:
ET1 : EventTriggerId1
Then we can have the sequence:
NT                                                     LT
|                                                        |
triggerEvent(ET1) ----------------> (TAW=0x00000001)
triggerEvent(ET1) ----------------> (TAW=0x00000001)
                                                           ---------------
                                                                             | singleStep()
                                                                             | handle ET1 by calling EH1

This might be intended behaviour, but it is not immediately clear when reading the function description:

"  virtual void triggerEvent(EventTriggerId eventTriggerId, void* clientData = NULL) = 0;
      // Causes the (previously-registered) handler function for the specified event to be handled (from the event loop).
      // The handler function is called with "clientData" as parameter.
      // Note: This function (unlike other library functions) may be called from an external thread
      // - to signal an external event.  (However, "triggerEvent()" should not be called with the
      // same 'event trigger id' from different threads.)"


The above is an issue for us and a possible solution would be for us to subclass BasicTaskScheduler and implement our own event handling, but it might also be possible to improve the live555 code and/or descriptions. If the code should be kept lock-free, I see a possible fix in converting fTriggersAwaitingHandling to an array, so that different eventIds have separate memory locations. This does however not address all the mentioned issues, and such a change will probably also consume more CPU cycles.

Best Regards

Jan Rørgaard Hansen
Lead Software Developer
Communication Solutions
Business Area Surveillance

Tel.:  + 45 3638 3000
E-mail: jan.r.hansen at dk.saabgroup.com





Saab Danmark A/S
Porten 6
DK – 6400 Sonderborg                        
www.saabgroup.com

This e-mail is private and confidential between the sender and the addressee. 
In the event of misdirection, the recipient is prohibited from using, copying or 
disseminating it or information in it. Please notify the above if any misdirection.


-----Original Message-----
From: live-devel <live-devel-bounces at us.live555.com> On Behalf Of Ross Finlayson
Sent: 31. maj 2023 23:41
To: LIVE555 Streaming Media - development & use <live-devel at us.live555.com>
Subject: [EXTERNAL] Re: [Live-devel] Possible concurrency issue with triggerEvent()

I’m really not interested in engaging in random speculation about this, because (based on experience) that quickly becomes a ’rat hole’.

If you have definitive proof that there’s a race condition that’s causing your problem, then I’m interested in hearing about it.  But your problem might well have some other cause.

For the record, here is the lone statement that updates “fTriggersAwaitingHandling” in our implementation of “triggerEvent()” - the only place where that variable can be updated by a non-LIVE555 thread:
	fTriggersAwaitingHandling |= eventTriggerId;


Ross Finlayson
Live Networks, Inc.
https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2fwww.live555.com&umid=bcd411c0-7af7-42df-940c-ee334a33599b&auth=6fca480dbae84d44d0c59caf48b50be59d1f5da5-abd6a4fe2e7209310ef2a39188906fffb75531be


_______________________________________________
live-devel mailing list
live-devel at lists.live555.com
https://smex-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=http%3a%2f%2flists.live555.com%2fmailman%2flistinfo%2flive%2ddevel&umid=bcd411c0-7af7-42df-940c-ee334a33599b&auth=6fca480dbae84d44d0c59caf48b50be59d1f5da5-82d006f8723635ffc49f0186148c7cb44497e81f
-------------- next part --------------
A non-text attachment was scrubbed...
Name: triggerRace.tar.gz
Type: application/x-gzip
Size: 4185 bytes
Desc: triggerRace.tar.gz
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20230607/ea0bc806/attachment.bin>


More information about the live-devel mailing list