NEventSocket icon indicating copy to clipboard operation
NEventSocket copied to clipboard

SubscribeEvents may not be Thread-Safe

Open DanieleGhianda opened this issue 3 years ago • 2 comments

I was using InboundSocket to originate some calls and play Audio files, and sometimes i got an ThrowInvalidOperationException_ConcurrentOperationsNotSupported where I called Play(...).

Here is the call stack:

    System.ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
    System.Collections.Generic.HashSet<T>.FindItemIndex(T)
    System.Collections.Generic.HashSet<T>.Contains(T)
    NEventSocket.Sockets.EventSocket.SubscribeEvents.AnonymousMethod__28_0(NEventSocket.FreeSwitch.EventName)
    System.Linq.Enumerable.All<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, bool>)
    NEventSocket.Sockets.EventSocket.SubscribeEvents(NEventSocket.FreeSwitch.EventName[])
    NEventSocket.Sockets.EventSocket.ExecuteApplication(string, string, string, bool, bool, int)
    NEventSocket.ApplicationExtensions.Play(NEventSocket.Sockets.EventSocket, string, string, NEventSocket.FreeSwitch.PlayOptions)

I checked the library and I noticed the use of HashSet: private readonly HashSet<EventName> subscribedEvents = new HashSet<EventName>();

Am I missing something or is it really not Thread-Safe ?

DanieleGhianda avatar Nov 26 '21 10:11 DanieleGhianda

It should be a ConcurrentHashSet<T> or introduce a lock mechanism if it’s being used concurrently.

That said, you might be putting a lot of workload on one socket connection if you’re having concurrency issues.

If that socket connection fails, and it’s managing all of your telecoms traffic - it’s going to affect all of your traffic.

The library assumes a 1:1 socket to call relationship, but I do know some users are using one socket for everything.

You can also make use of freeswitch’s internal scheduler for handing off tasks in bulk.

Can you describe your use case?

danbarua avatar May 09 '23 10:05 danbarua

If this scenario is occurring in simple test code, then you may be missing an await somewhere, so the runtime will continue onto the next socket API call before the previous one has completed and reported back.

danbarua avatar May 09 '23 10:05 danbarua