Story 3 -- Proxies confront Hooks
We've got a number of reports about Visual Studio crash when doing repository operations using TFS. Of course, when ReSharper is disabled, no crashes occurs, which make users think ReSharper is guilty. We couldn't reproduce the problem in the labs, and we again tried to assert/log/verify everything we can think about. We even got some dumps with the crash, but could not find anything really useful there, besides evidence that there are numerous SecurityExceptions instances in the managed heap waiting to be collected. We needed reproducible case with WinDbg attached. Thanks to Vasily, we got one.
It is funny how we were debugging this crash. Since we were not able to reproduce the problem in the labs, we needed access to the faulty computer. However, due to corporate rules on the user's side, we were not able to arrange real remote session. But we had WinDbg with command line interface, and we had instant messaging. So I was sending WinDbg commands, he copied them into WinDbg, executed, and then copied back the result. We laughed about it and were kidding about extension to WinDbg which would be Jabber client :)
After several days being in this copy-paste process, we finally found the problem. Three components playing together made it explosive:
- Connecting to web site with HTTP when automatic proxy configuration script is enabled (It is basically JScript function which gives proxy address for given host)
- Managed hooks installed (here is ReSharper's role in the problem, but could be any other plugin)
- Pumping messages during JScript code execution
Remove one, and all is fine again. So, what is happening in our case? Now, watch my hands.
- TeamFoundation client is going to communicate to server.
- It initiates connection to web service.
- HttpWebRequest is asking for proxy information.
- WebProxy detects that automatic proxy configuration script is enabled.
- AutoWebProxyScriptEngine downloads script and uses JScript engine to execute it
- JScript engine restricts code permissions to execute only.
- Exception happens while executing JScript and dialog is going to be shown with error information. This is who pumps messages.
- Our managed hook is executed and attempts to use CallNextHookEx to pass data to other hooks.
- Code Access Security system demands UnmanagedCode permission.
- Due to restricted mode in which JScript executes, demand fails and SecurityException is rised.
- Exception causes corruption of some internal Visual Studio COM objects, which instantly leads to Access Violation.
Well, actually, this one was our fault. I added SecurityPermissionAttribute asserting UnmanagedCode permission to the hook procedure and ReSharper is shining like a diamond again.
Case closed, lessons learned.