c++ - DCOM: How to close connection in server on client crash? -
i have rather old project: dcom client , server, both in c++\atl, windows platform. works fine: local , remote clients connect server , work simultaneously without problem.
but when remote client crashes or being killed task manager or "taskkill" command or power switch off - have problem. server not know client crash , tries send new events clients (also crashed). result have pause (server can not send data crashed client) , it's duration proportional numbers of crashed remote clients. after 5 crashed clients pauses long equal server stop.
i know dcom "ping" mechanism (dcom should disconnect clients not respond "every 2 minutes ping" after 6 minutes of silence). , really, after 6 minutes of hang have small period of normal work server coming "paused" state.
what can of this? how make dcom "ping" works fine? if implement own "ping" code possible disconnect old dcom clients connection manually? how it?
i'm not sure dcom ping system, 1 option farm off notifications separate thread pool. mitigate effect of having small number of blocking clients - you'll start having problems when there many though, of course.
the easy way use queueuserworkitem
- invoke passed callback on application's system thread pool. assuming you're using mta, need do:
static infostruct { iremotehost *premote; bstr somedata; }; static dword winapi invokeclientasync(lpvoid lpinfo) { coinitializeex(coinit_multithreaded); infostruct *is = (infostruct *)lpinfo; is->premote->notify(somedata); is->premote->release(); sysfreestring(is->somedata); delete is; couninitialize(); return 0; } void invokeclient(iremotehost *premote, bstr somedata) { infostruct *is = new infostruct; is->premote = premote; premote->addref(); is->somedata = sysallocstring(somedata); queueuserworkitem(invokeclientasync, (lpvoid)is, wt_executelongfunction); }
if main thread in sta, more complex; have use comarshalinterthreadinterfaceinstream
, cogetinterfaceandreleasestream
pass interface pointer between apartments:
static infostruct { istream *pmarshalledremote; bstr somedata; }; static dword winapi invokeclientasync(lpvoid lpinfo) { coinitializeex(coinit_multithreaded); // can sta infostruct *is = (infostruct *)lpinfo; iremotehost *premote; cogetinterfaceandreleasestream(is->pmarshalledremote, __uuidof(iremotehost), (lpvoid *)&premote); premote->notify(somedata); premote->release(); sysfreestring(is->somedata); delete is; couninitialize(); return 0; } void invokeclient(iremotehost *premote, bstr somedata) { infostruct *is = new infostruct; comarshalinterthreadinterfaceinstream(__uuidof(iremotehost), premote, &is->pmarshalledremote); is->somedata = sysallocstring(somedata); queueuserworkitem(invokeclientasync, (lpvoid)is, wt_executelongfunction); }
note error checking has been elided clarity - of course want error check calls - in particular, want checking rpc_s_server_unavailable
, other such network errors, , remove offending clients.
some more sophisticated variations may want consider include ensuring 1 request in-flight per client @ time (thus further reducing impact of stuck client) , caching marshalled interface pointer in mta (if main thread sta) - since believe comarshalinterthreadinterfaceinstream
may perform network requests, you'd ideally want take care of ahead of time when know client connected, rather risking blocking on main thread.
Comments
Post a Comment