Managed ESL: AccessViolationException
Hello, I'm trying to run the following code, but after a few seconds I get AccessViolationException: class Program { static void Main(string[] args) { ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon"); connection.SendRecv("event plain ALL"); Task task1 = Task.Run(() => Receive(1, connection)); Task task2 = Task.Run(() => Receive(2, connection)); Console.ReadLine(); } static void Receive(int id, ESLconnection connection) { while (connection.Connected() == 1) { ESLevent eslEvent = connection.RecvEvent(); Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]); } } } What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel. Does the exception occur because multiple parallel tasks are trying to access the connection object? Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID? Regards, Grant
Try pulling the latest git This issue was reported in http://jira.freeswitch.org/browse/ESL-81 and appears to have been resolved in February. On Fri, May 16, 2014 at 7:24 AM, Grant Bagdasarian <GB@cm.nl> wrote:
Hello,
I’m trying to run the following code, but after a few seconds I get AccessViolationException:
class Program {
static void Main(string[] args) {
ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon");
connection.SendRecv("event plain ALL");
Task task1 = Task.Run(() => Receive(1, connection));
Task task2 = Task.Run(() => Receive(2, connection));
Console.ReadLine();
}
static void Receive(int id, ESLconnection connection) {
while (connection.Connected() == 1) {
ESLevent eslEvent = connection.RecvEvent();
Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]);
}
}
}
What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel.
Does the exception occur because multiple parallel tasks are trying to access the connection object?
Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID?
Regards,
Grant
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hi Grant, TCP/IP sockets (in general) are designed to be owned by a single thread. It is not permitted to block on the same socket by two different threads. I don't know if this is your violation, but it is a problem. If you want multi-threaded task handlers, the correct socket design is to have one thread handling the socket (8021) reads, and sending the event read to separate task handlers (in parallel). The Receive() method is blocking for an event, and grabbing the first line of the event. Does the error occur when Receive() get's it's first event, or when the second thread tries to block on a socket that is already owned by thread 1? If you comment out "Task task2" does the error still occur? Ian. On Fri, May 16, 2014 at 7:24 AM, Grant Bagdasarian <GB@cm.nl> wrote:
Hello,
I’m trying to run the following code, but after a few seconds I get AccessViolationException:
class Program {
static void Main(string[] args) {
ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon");
connection.SendRecv("event plain ALL");
Task task1 = Task.Run(() => Receive(1, connection));
Task task2 = Task.Run(() => Receive(2, connection));
Console.ReadLine();
}
static void Receive(int id, ESLconnection connection) {
while (connection.Connected() == 1) {
ESLevent eslEvent = connection.RecvEvent();
Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]);
}
}
}
What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel.
Does the exception occur because multiple parallel tasks are trying to access the connection object?
Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID?
Regards,
Grant
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hello Ian, I ran the code and this was the output, before it threw the exception: The number is the id of the task. 1 - Event-Name: API 2 - Event-Name: HEARTBEAT 1 - Event-Name: RE_SCHEDULE 2 - Event-Name: API 1 - Event-Name: API 2 - Event-Name: CHANNEL_OUTGOING 1 - Event-Name: CHANNEL_STATE 1 - Event-Name: CHANNEL_ORIGINATE 1 - Event-Name: CHANNEL_STATE 1 - Event-Name: CHANNEL_STATE When I comment out the Task task2 line there is no error. As you said, I think this is what exactly happens: ” the second thread tries to block on a socket that is already owned by thread 1” Just to be sure, the same ESLconnection object can be used by multiple threads to receive and send events, as long as the socket reads aren’t done by multiple threads at once? Thanks Grant From: freeswitch-users-bounces@lists.freeswitch.org [mailto:freeswitch-users-bounces@lists.freeswitch.org] On Behalf Of Ian McMaster Sent: Friday, May 16, 2014 4:37 PM To: FreeSWITCH Users Help Subject: Re: [Freeswitch-users] Managed ESL: AccessViolationException Hi Grant, TCP/IP sockets (in general) are designed to be owned by a single thread. It is not permitted to block on the same socket by two different threads. I don't know if this is your violation, but it is a problem. If you want multi-threaded task handlers, the correct socket design is to have one thread handling the socket (8021) reads, and sending the event read to separate task handlers (in parallel). The Receive() method is blocking for an event, and grabbing the first line of the event. Does the error occur when Receive() get's it's first event, or when the second thread tries to block on a socket that is already owned by thread 1? If you comment out "Task task2" does the error still occur? Ian. On Fri, May 16, 2014 at 7:24 AM, Grant Bagdasarian <GB@cm.nl<mailto:GB@cm.nl>> wrote: Hello, I’m trying to run the following code, but after a few seconds I get AccessViolationException: class Program { static void Main(string[] args) { ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon"); connection.SendRecv("event plain ALL"); Task task1 = Task.Run(() => Receive(1, connection)); Task task2 = Task.Run(() => Receive(2, connection)); Console.ReadLine(); } static void Receive(int id, ESLconnection connection) { while (connection.Connected() == 1) { ESLevent eslEvent = connection.RecvEvent(); Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]); } } } What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel. Does the exception occur because multiple parallel tasks are trying to access the connection object? Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID? Regards, Grant _________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org<mailto:consulting@freeswitch.org> http://www.freeswitchsolutions.com FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org<mailto:FreeSWITCH-users@lists.freeswitch.org> http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hi Grant, Glad things are starting to work out. I would say that if you properly protect (by a semaphore, etc) access to your socket connection to ensure a read is exclusive to one thread you will be fine. Maybe it is a better idea in the long run to have a dedicated connection/socket for a hangup listener? I have a large event subsystem, and my design is to have a parent thread listening for all events, and distributing those events (i.e. ESLevent) to interested listeners (by event type). In this way there is only one socket connection related to event listening. Could one connection feed the ESLevents to both your hangup listener (task 1), and your general call processor (task 2)? Ian. On Mon, May 19, 2014 at 3:51 AM, Grant Bagdasarian <GB@cm.nl> wrote:
Hello Ian,
I ran the code and this was the output, before it threw the exception:
The number is the id of the task.
1 - Event-Name: API
2 - Event-Name: HEARTBEAT
1 - Event-Name: RE_SCHEDULE
2 - Event-Name: API
1 - Event-Name: API
2 - Event-Name: CHANNEL_OUTGOING
1 - Event-Name: CHANNEL_STATE
1 - Event-Name: CHANNEL_ORIGINATE
1 - Event-Name: CHANNEL_STATE
1 - Event-Name: CHANNEL_STATE
When I comment out the Task task2 line there is no error.
As you said, I think this is what exactly happens: ” the second thread tries to block on a socket that is already owned by thread 1”
Just to be sure, the same ESLconnection object can be used by multiple threads to receive and send events, as long as the socket reads aren’t done by multiple threads at once?
Thanks
Grant
*From:* freeswitch-users-bounces@lists.freeswitch.org [mailto: freeswitch-users-bounces@lists.freeswitch.org] *On Behalf Of *Ian McMaster *Sent:* Friday, May 16, 2014 4:37 PM *To:* FreeSWITCH Users Help *Subject:* Re: [Freeswitch-users] Managed ESL: AccessViolationException
Hi Grant,
TCP/IP sockets (in general) are designed to be owned by a single thread. It is not permitted to block on the same socket by two different threads. I don't know if this is your violation, but it is a problem.
If you want multi-threaded task handlers, the correct socket design is to have one thread handling the socket (8021) reads, and sending the event read to separate task handlers (in parallel).
The Receive() method is blocking for an event, and grabbing the first line of the event.
Does the error occur when Receive() get's it's first event, or when the second thread tries to block on a socket that is already owned by thread 1?
If you comment out "Task task2" does the error still occur?
Ian.
On Fri, May 16, 2014 at 7:24 AM, Grant Bagdasarian <GB@cm.nl> wrote:
Hello,
I’m trying to run the following code, but after a few seconds I get AccessViolationException:
class Program {
static void Main(string[] args) {
ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon");
connection.SendRecv("event plain ALL");
Task task1 = Task.Run(() => Receive(1, connection));
Task task2 = Task.Run(() => Receive(2, connection));
Console.ReadLine();
}
static void Receive(int id, ESLconnection connection) {
while (connection.Connected() == 1) {
ESLevent eslEvent = connection.RecvEvent();
Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]);
}
}
}
What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel.
Does the exception occur because multiple parallel tasks are trying to access the connection object?
Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID?
Regards,
Grant
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
_________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org http://www.freeswitchsolutions.com
FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com
Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com
FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
Hello Ian, I’ve built my first application using ESL (direct with no wrappers), but I’m going to be working on a library which encapsulates all the ESL objects/methods found in the ESL library to make it easier to build applications. I was going in the same direction as you suggested, one parent thread for socket reads and distributing the events to all its subscribers. “Could one connection feed the ESLevents to both your hangup listener (task 1), and your general call processor (task 2)?” It could, but I believe it could not in a specific situation I have, for which I’m using outbound socket: call comes into FS, call control is handed to my C# app (outbound socket). The incoming leg gets bridged to another (b leg). They get separated after X minutes, which leaves you with 2 separated channels. Depending on the input of the a leg, the calls should be connected. But if the A leg hangs up, the B leg remains in parked state and for some reason the outbound ESL connection is also disconnected. This has forced me to create another inbound ESL socket just to monitor the hangup of the A leg. I posted about this in my other thread I created, which was also answered by you. Thanks for your help! Regards, Grant From: freeswitch-users-bounces@lists.freeswitch.org [mailto:freeswitch-users-bounces@lists.freeswitch.org] On Behalf Of Ian McMaster Sent: Monday, May 19, 2014 3:34 PM To: FreeSWITCH Users Help Subject: Re: [Freeswitch-users] Managed ESL: AccessViolationException Hi Grant, Glad things are starting to work out. I would say that if you properly protect (by a semaphore, etc) access to your socket connection to ensure a read is exclusive to one thread you will be fine. Maybe it is a better idea in the long run to have a dedicated connection/socket for a hangup listener? I have a large event subsystem, and my design is to have a parent thread listening for all events, and distributing those events (i.e. ESLevent) to interested listeners (by event type). In this way there is only one socket connection related to event listening. Could one connection feed the ESLevents to both your hangup listener (task 1), and your general call processor (task 2)? Ian. On Mon, May 19, 2014 at 3:51 AM, Grant Bagdasarian <GB@cm.nl<mailto:GB@cm.nl>> wrote: Hello Ian, I ran the code and this was the output, before it threw the exception: The number is the id of the task. 1 - Event-Name: API 2 - Event-Name: HEARTBEAT 1 - Event-Name: RE_SCHEDULE 2 - Event-Name: API 1 - Event-Name: API 2 - Event-Name: CHANNEL_OUTGOING 1 - Event-Name: CHANNEL_STATE 1 - Event-Name: CHANNEL_ORIGINATE 1 - Event-Name: CHANNEL_STATE 1 - Event-Name: CHANNEL_STATE When I comment out the Task task2 line there is no error. As you said, I think this is what exactly happens: ” the second thread tries to block on a socket that is already owned by thread 1” Just to be sure, the same ESLconnection object can be used by multiple threads to receive and send events, as long as the socket reads aren’t done by multiple threads at once? Thanks Grant From: freeswitch-users-bounces@lists.freeswitch.org<mailto:freeswitch-users-bounces@lists.freeswitch.org> [mailto:freeswitch-users-bounces@lists.freeswitch.org<mailto:freeswitch-users-bounces@lists.freeswitch.org>] On Behalf Of Ian McMaster Sent: Friday, May 16, 2014 4:37 PM To: FreeSWITCH Users Help Subject: Re: [Freeswitch-users] Managed ESL: AccessViolationException Hi Grant, TCP/IP sockets (in general) are designed to be owned by a single thread. It is not permitted to block on the same socket by two different threads. I don't know if this is your violation, but it is a problem. If you want multi-threaded task handlers, the correct socket design is to have one thread handling the socket (8021) reads, and sending the event read to separate task handlers (in parallel). The Receive() method is blocking for an event, and grabbing the first line of the event. Does the error occur when Receive() get's it's first event, or when the second thread tries to block on a socket that is already owned by thread 1? If you comment out "Task task2" does the error still occur? Ian. On Fri, May 16, 2014 at 7:24 AM, Grant Bagdasarian <GB@cm.nl<mailto:GB@cm.nl>> wrote: Hello, I’m trying to run the following code, but after a few seconds I get AccessViolationException: class Program { static void Main(string[] args) { ESLconnection connection = new ESLconnection("192.168.1.1", 8021, "ClueCon"); connection.SendRecv("event plain ALL"); Task task1 = Task.Run(() => Receive(1, connection)); Task task2 = Task.Run(() => Receive(2, connection)); Console.ReadLine(); } static void Receive(int id, ESLconnection connection) { while (connection.Connected() == 1) { ESLevent eslEvent = connection.RecvEvent(); Console.WriteLine("{0} - {1}", id, eslEvent.Serialize("").Split(new char[] { '\r', '\n' })[0]); } } } What the basic idea behind this is, is to have a Task continuously listening for a CHANNEL_HANGUP event, and have the other Task process the call in parallel. Does the exception occur because multiple parallel tasks are trying to access the connection object? Is the only solution to create a second ESLconnection (HANGUP Handler) and register it to receive only calls for a given UUID? Regards, Grant _________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org<mailto:consulting@freeswitch.org> http://www.freeswitchsolutions.com FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org<mailto:FreeSWITCH-users@lists.freeswitch.org> http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org _________________________________________________________________________ Professional FreeSWITCH Consulting Services: consulting@freeswitch.org<mailto:consulting@freeswitch.org> http://www.freeswitchsolutions.com FreeSWITCH-powered IP PBX: The CudaTel Communication Server http://www.cudatel.com Official FreeSWITCH Sites http://www.freeswitch.org http://wiki.freeswitch.org http://www.cluecon.com FreeSWITCH-users mailing list FreeSWITCH-users@lists.freeswitch.org<mailto:FreeSWITCH-users@lists.freeswitch.org> http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
participants (3)
-
Duvid Rottenberg
-
Grant Bagdasarian
-
Ian McMaster