EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Sending Messages from Multiple Threads

Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages
Posted: 01/22/2010 08:55:53
by Malcolm Toon (Standard support level)
Joined: 01/20/2010
Posts: 22

I am trying to use MsgConnect to be a gateway between a current TCP protocol and another. Basically, I have a multi-threaded TCP server that is listening for connection for a proprietary protocol. When connections are established (thus creating a new thread), I am trying to send MC messages (blocking and non-blocking) from these connection threads to the other MC node. I'm currently testing this out from within a single application (so, basically, sending messages to the socket transport within the same application) for processing. I keep getting an AV from within the DispatchMessages method

if AQueue <> nil then
{$IFDEF MC_DEBUG}Logger.PutMessage(llInformation, Format('Message %d -- queue found', [Info.Message.MsgCode]), 0, 'DispatchMessages'); {$ENDIF}
-- D7's debugger keeps stoping on this line:

The call stack is showing that this is within the SendMessage from within the TCP connection's thread (not the DispatchMessages that's called from the timer).

Here's the call stack:
--- my routine here

Any thoughts? I checked out the file transfer and the IM demos and those seem to all run within the main thread. I'm sure it's something simple like I'm just making the wrong call to send the message or something like that.

Thank you!
Posted: 01/22/2010 09:04:03
by Malcolm Toon (Standard support level)
Joined: 01/20/2010
Posts: 22

More info..
I stepped through this more and realized the AV was being raise by my UnhandledMessage event handler, but this is the only code there..

The AV was popping up on the Message.Result:=-1; line. So, now my question is: why is the UnhandledMessage event being fired during the send phase (before the message is queued?) and also, my guess is the reason for the AV is that the Message variable is invalid, so question 2 is: why would MC be calling this event handler with an invalid message?

Thank you again-
Posted: 01/22/2010 09:11:21
by Malcolm Toon (Standard support level)
Joined: 01/20/2010
Posts: 22

More info..
Oddly, when I inspect Info.Message here, I get the right info (see attached picture)
if Assigned(OnUnhandledMessage) then
OnUnhandledMessage(Self, Info.Message, Handled);

But when I step into the event handler.. the inspector shows an entirely different set of values.
The snapshot on the left is pre-event call, two F7's later once I've stepped into the event handler, the inspector is showing the values on the right.


Posted: 01/22/2010 10:33:52
by Eugene Mayevski (Team)

When you call one of MCMessenger's methods, MCMessenger calls DispatchMessages to process the incoming messages and outgoing messages which have expired or for which the reply was received. So you get OnUnhandledMessage for some incoming message, not for the message you are sending. The question is where this incoming message comes from. And the AV can happen if the message is dispatched by several threads in parallel.

Your multithreaded approach is legitimate and has been tested (and appeared to work fine). There are synchronization primitives guarding the incoming queue, so handling of one message by several threads is nearly impossible. But if it happens, we need to investigate it - internal synchronization is very complex in MsgConnect.

In order for us to do the test, we would need a test case from you which reproduces the issue. You can create several sender threads which will send messages all the time (with some interval of course) and one or more receiver threads that correspond to receiver in your application design. Those receivers need to have different set of MsgConnect objects.

Please submit test's source code here or to HelpDesk.

If you create the test case today or tomorrow, I will have possibility to play with it on Sunday.

Sincerely yours
Eugene Mayevski
Posted: 01/22/2010 12:17:38
by Malcolm Toon (Standard support level)
Joined: 01/20/2010
Posts: 22

I was able to reproduce the problem in the StressTest application. I added a Message Handler to the queue object and set an event handler for it. This is the code within the event handler. It produces the same AV problem.


It seems that I am having problems accessing the Message variable within the event handler and I can't figure out why. I changed the event calling code to make sure:
Handlers[i].OnMessage(Self, FMessage, Handled);

The FMessage variable is of type TMCMessage. FMessage evaluates correctly, but
procedure TStressTestFrm.queueHandlers0Message(Sender: TObject;
var Message: TMCMessage; var Handled: Boolean);

Shows Message as being null. I'm starting to wonder if this could somehow be a delphi thing. Have you ever seen this before?

Thank you-
Posted: 01/22/2010 12:29:49
by Eugene Mayevski (Team)

Damn. Have you declared the event handler as stdcall? Documentation mentions this. This is a strange (from delphi point of view) requirement, but now it's not time to change it, as it was present from the very beginning of MsgConnect existence. All events *except* the ones of TMCInetTransport must be declared as stdcall.

Sincerely yours
Eugene Mayevski
Posted: 01/22/2010 12:38:47
by Malcolm Toon (Standard support level)
Joined: 01/20/2010
Posts: 22

Thank you! That's exactly it. I should have noticed that when I looked up the event handler declarations. Typical developer... write code first, never read any documentation and then ask questions!

Thanks again!
Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.



Topic viewed 5032 times

Number of guests: 1, registered members: 0, in total hidden: 0


Back to top

As of July 15, 2016 EldoS business operates as a division of /n software, inc. For more information, please read the announcement.

Got it!