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
triggerRace.tar.gz
Description: triggerRace.tar.gz
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel