While working on a custom WCF transport channel implementation I ran into a problem that baffled me for a while. As usual, the problem ended being caused by my own fault, but it was hard to figure what was actually going wrong :-).
The problem revolved around a the ChannelListener for the service side of the transport, which was getting executed through a normal WCF-provided
ServiceHost (as opposed to using the channel model directly). The puzzling behavior I was seeing while testing and lots of stepping around in the debugger was like this:
ServiceHostwould open my
ChannelListenerimplementation, which in turn would mean my
OnOpen()method would get executed.
- The host would then do a
BeginAcceptChannel()call on my listener with an infinite timeout. The listener gladly processed the request and returned the corresponding
- Meanwhile, the channel listener was busy doing it’s thing, and, within a few hundred milliseconds, would produce a new
IInputChanneland signal the
WaitHandlereturned in the
- The host would wake up after the wait handle was signal and call the listener’s
EndAcceptChannel(), which promptly returned the new queued input channel instance.
- … And that was it. Nothing else happened. The host would not call any method on the
IInputChannelreturned. Not Open(), much less posting a wait or a receive for a message. Obviously, the whole thing would grind up to a halt at this point, but no errors would get raised, the service host did not fault and there wasn’t anything suspicious logged to the ServiceModel activity traces.
What was going on? Well, it seems that the
OnOpen() implementation in my
ChannelListener was actually blocking, instead of returning control right away. I’m not sure if this was an effect of how the async variant of the call was working, but the end result was that as far as the service host was concerned, the listener had, not completed initializing, so it just didn’t do anything else.
What really confused me while troubleshooting this problem was that because
BeginAcceptChannel() was getting called, it didn’t even occur to me to look into the opening of the listener; I just assumed that if the host was trying to accept a channel, the listener had successfully opened. Looks like this isn’t as clear cut as this.
Once I fixed the blocking open of the channel listener, the host started calling my input channel methods again and everything went back to normal. Lesson learned.