I'm not sure if this is a "lessons learned" thread or a "feature request" thread. I'll let jcl decide if he wants. laugh

Here's a code snippet that will freeze Zorro from the broker DLL plugin:

Code:
// various headers omitted
#define PLUGIN_VERSION	2
////////////////////////////////////////////////////////////////
extern "C" __declspec(dllexport) BrokerOpen(char* Name, FARPROC fpError, FARPROC fpProgress)
{
	strcpy_s(Name, 32, "TEST Callback");
	(FARPROC&)BrokerError = fpError;
	(FARPROC&)BrokerProgress = fpProgress;
	return PLUGIN_VERSION;
}

extern "C" __declspec(dllexport) BrokerLogin(char* User, char* Pwd, char* Type, char* Accounts)
{
	std::thread tcp_listener_thread([&]() {
		BrokerProgress(0); // I want to trigger a tick read on a dedicated listener thread.
		BrokerError("hello world");
	});
	tcp_listener_thread.join();
	return 0;
}



So what happened here?

1) BrokerError and BrokerProgress both invoke Zorro functions.
2) Zorro invokes BrokerLogin on this test DLL.
3) BrokerLogin starts a new thread tcp_listener_thread.
4) BrokerLogin waits for the thread to return & rejoin.

Meanwhile at tcp_listener_thread...
1) BrokerProgress tries to call Zorro. It freezes here because the zorro thread is occupied with BrokerLogin.
2) If BrokerProgress were commented out, the thread would freeze at the very next line for the same exact reason as the last.

In practice, a listener thread would make callbacks when the Zorro thread is occupied or not occupied. A plugin writer would have to account for both cases.

Possible workarounds involve forcing callbacks on the Zorro thread only, or some combination of std::atomic<bool> and using class instances whose destructors indicate thread availability, for example.

In conclusion, I think it would be nice if one of these two things happened:
1) Revise the manual to indicate that callbacks should only be issued when the zorro thread is unoccupied and recommend workarounds, or
2) A dedicated Zorro thread listens to / queues broker DLL callbacks.