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.han...@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-boun...@us.live555.com> On Behalf Of Ross Finlayson
Sent: 31. maj 2023 23:41
To: LIVE555 Streaming Media - development & use <live-de...@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@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

Attachment: triggerRace.tar.gz
Description: triggerRace.tar.gz

_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to