|
22 | 22 | using System.Text.RegularExpressions; |
23 | 23 | using System.Threading.Tasks; |
24 | 24 | using Microsoft.NodejsTools.Logging; |
| 25 | +using Microsoft.VisualStudioTools; |
25 | 26 | using Microsoft.VisualStudioTools.Project; |
26 | 27 | using Newtonsoft.Json; |
27 | 28 |
|
@@ -112,10 +113,49 @@ public Version NodeVersion { |
112 | 113 | /// <param name="uri">URI identifying the endpoint to connect to.</param> |
113 | 114 | public void Connect(Uri uri) { |
114 | 115 | Utilities.ArgumentNotNull("uri", uri); |
| 116 | + LiveLogger.WriteLine("Debugger connecting to URI: {0}", uri); |
115 | 117 |
|
116 | 118 | Close(); |
117 | 119 | lock (_networkClientLock) { |
118 | | - _networkClient = _networkClientFactory.CreateNetworkClient(uri); |
| 120 | + int connection_attempts = 0; |
| 121 | + const int MAX_ATTEMPTS = 5; |
| 122 | + while (true) { |
| 123 | + connection_attempts++; |
| 124 | + try { |
| 125 | + // TODO: This currently results in a call to the synchronous TcpClient |
| 126 | + // constructor, which is a blocking call, and can take a couple of seconds |
| 127 | + // to connect (with timeouts and retries). This code is running on the UI |
| 128 | + // thread. Ideally this should be connecting async, or moved off the UI thread. |
| 129 | + _networkClient = _networkClientFactory.CreateNetworkClient(uri); |
| 130 | + |
| 131 | + // Unclear if the above can succeed and not be connected, but check for safety. |
| 132 | + // The code needs to either break out the while loop, or hit the retry logic |
| 133 | + // in the exception handler. |
| 134 | + if (_networkClient.Connected) { |
| 135 | + LiveLogger.WriteLine("Debugger connected successfully"); |
| 136 | + break; |
| 137 | + } |
| 138 | + else { |
| 139 | + throw new SocketException(); |
| 140 | + } |
| 141 | + } |
| 142 | + catch (Exception ex) { |
| 143 | + if (ex.IsCriticalException()) { |
| 144 | + throw; |
| 145 | + } |
| 146 | + LiveLogger.WriteLine("Connection attempt {0} failed with: {1}", connection_attempts, ex); |
| 147 | + if (connection_attempts >= MAX_ATTEMPTS) { |
| 148 | + throw; |
| 149 | + } |
| 150 | + else { |
| 151 | + // See above TODO. This should be moved off the UI thread or posted to retry |
| 152 | + // without blocking in the meantime. For now, this seems the lesser of two |
| 153 | + // evils. (The other being the debugger failing to attach on launch if the |
| 154 | + // debuggee socket wasn't open quickly enough). |
| 155 | + System.Threading.Thread.Sleep(200); |
| 156 | + } |
| 157 | + } |
| 158 | + } |
119 | 159 | } |
120 | 160 |
|
121 | 161 | Task.Factory.StartNew(ReceiveAndDispatchMessagesWorker); |
|
0 commit comments