On Thu, Jul 19, 2012 at 7:35 PM, Timo Teras <timo.teras at iki.fi> wrote: > On Thu, 19 Jul 2012 14:27:14 +0700 Benny Prijono <bennylp at teluu.com> > wrote: > > > On Thu, Jul 19, 2012 at 1:19 PM, Timo Teras <timo.teras at iki.fi> wrote: > > > > > > > > Solutions that come up to my mind: > > > > > > - if the pool is deleted, the destructor should wait synchronously > > > that each cancel notification is received before continuing > > > > > Well I've figured what the alternative solutions are, it's just that I > > don't find them simple to implement. > > Now that I actuall read the code, it seems that the > pj_ioqueue_unregister() is trying to achieve the synchronous operation > if PJ_IOQUEUE_HAS_SAFE_UNREG is defined. The SAFE_UNREG seems to also > enable lot of probably unnecessary "workaround" code. > > However, this does not work if poll_iocp() is not called from another > thread while pj_ioqueue_unregister() is synchronizing in the busy loop. > > Fundamental problem here seem to be that pj_ioqueue_unregister() is > assumed to be synchronous, but the underlaying windows API is > asynchronous. And it's not easy to convert it to synchronous one, > unless there're separate threads calling poll_iocp concurrently. > Do note that this is the standard design: one should have multiple > threads blocking in GetQueuedCompletionStatus() that act as a thread > pool to process the completions. > > As a workaround in single threaded programs: the _unregister() could > instead of sleep(0) call GetQueuedCompletionStatus() and stuff the > received events in a "pending" list which would get priority on next > call of poll. And of course handle immediately the events for the > handle it's waiting for. > > But yes - either of these can be slightly tricky due to > pj_ioqueue_unregister() being expected to be synchronous and the fact > that windows API works asynchronously. > > Additionally - it would seem that sip_endpoint.c in udp_destroy() does > actually first call unregister for all keys, and then poll for the > actual cancel events. However, one should not stop polling when there's > no io events - windows driver clean up can take a little time, and make > a first poll return no events after cancel request is posted. > > Sounds to me that the ioqueue is not well defined on how the > unregistration happens. And different parts of the code make slightly > different assumptions. > > The spec is aimed to be very simple. Once unregister is called, the key should be dead. All of those additional spec and code are precisely the workarounds due to IOCP. Now it seems like you know your stuff, it would be great it you could find a fix in the unregistration procedure. Cheers Benny > As final note - it seems one can have multiple ioqueues in a process. > It is also notable that in Windows you can have one thread call > GetQueuedCompletionStatus() for single queue only. The remarks say: > This function associates a thread with the specified completion port. > A thread can be associated with at most one completion port. > This is likely to tie it up the thread to be included in > CreateIoCompletionPort() call's NumberOfConcurrentThreads when the > thread is in running state. > > This basically implies that each ioqueue should have their dedicated > pool of threads that handle the overlapped events. Dunno how the > ioqueues are nested in pjsip core code, though. > > - Timo > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20120720/8d5a456b/attachment.html>