about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2024-12-18 14:13:39 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2024-12-18 14:13:39 -0500
commit62f2eb908c6771f9ac89aa518c55fbc101df3447 (patch)
tree5e2410248dcbba40625c271a857549140f7b9e56
parent2844eecb65501f7dafa4de15d7377bfb810e1158 (diff)
downloadlingo-ap-tracker-62f2eb908c6771f9ac89aa518c55fbc101df3447.tar.gz
lingo-ap-tracker-62f2eb908c6771f9ac89aa518c55fbc101df3447.tar.bz2
lingo-ap-tracker-62f2eb908c6771f9ac89aa518c55fbc101df3447.zip
Handle exceptions when starting IPC connection
Also fixes bug where the IPC thread would double-lock the state mutex if the connection timed out and reached the maximum backoff interval.
-rw-r--r--src/ipc_state.cpp68
1 files changed, 41 insertions, 27 deletions
diff --git a/src/ipc_state.cpp b/src/ipc_state.cpp index 24d0115..62b1828 100644 --- a/src/ipc_state.cpp +++ b/src/ipc_state.cpp
@@ -112,8 +112,6 @@ struct IPCState {
112 private: 112 private:
113 void Thread() { 113 void Thread() {
114 for (;;) { 114 for (;;) {
115 SetStatusMessage("Disconnected from game.");
116
117 // initialized is definitely true because it is set to true when the thread 115 // initialized is definitely true because it is set to true when the thread
118 // is created and only set to false within this block, when the thread is 116 // is created and only set to false within this block, when the thread is
119 // killed. Thus, a call to Connect would always at most set 117 // killed. Thus, a call to Connect would always at most set
@@ -127,6 +125,8 @@ struct IPCState {
127 { 125 {
128 std::lock_guard state_guard(state_mutex); 126 std::lock_guard state_guard(state_mutex);
129 127
128 SetStatusMessage("Disconnected from game.");
129
130 should_disconnect = false; 130 should_disconnect = false;
131 131
132 slot_matches = false; 132 slot_matches = false;
@@ -142,34 +142,49 @@ struct IPCState {
142 } 142 }
143 143
144 ipc_address = address; 144 ipc_address = address;
145
146 SetStatusMessage("Connecting to game...");
145 } 147 }
146 148
147 int backoff_amount = 0; 149 int backoff_amount = 0;
148 150
149 SetStatusMessage("Connecting to game...");
150 TrackerLog(fmt::format("Looking for game over IPC ({})...", ipc_address)); 151 TrackerLog(fmt::format("Looking for game over IPC ({})...", ipc_address));
151 152
152 while (!TryConnect(ipc_address) || !connected) { 153 while (!connected) {
153 int backoff_limit = (backoff_amount + 1) * 10; 154 if (TryConnect(ipc_address)) {
154 155 int backoff_limit = (backoff_amount + 1) * 10;
155 for (int i = 0; i < backoff_limit && !connected; i++) { 156
156 // If Connect is called right before this block, we will see and handle 157 for (int i = 0; i < backoff_limit && !connected; i++) {
157 // should_disconnect. If it is called right after, we will do one bad 158 // If Connect is called right before this block, we will see and
158 // poll, one sleep, and then grab the mutex again right after. 159 // handle should_disconnect. If it is called right after, we will do
159 { 160 // one bad poll, one sleep, and then grab the mutex again right
160 std::lock_guard state_guard(state_mutex); 161 // after.
161 if (should_disconnect) { 162 {
162 break; 163 std::lock_guard state_guard(state_mutex);
164 if (should_disconnect) {
165 break;
166 }
163 } 167 }
168
169 ws->poll();
170
171 // Back off
172 std::this_thread::sleep_for(std::chrono::milliseconds(100));
164 } 173 }
165 174
166 ws->poll(); 175 backoff_amount++;
176 } else {
177 std::lock_guard state_guard(state_mutex);
167 178
168 // Back off 179 if (!should_disconnect) {
169 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 180 should_disconnect = true;
170 } 181 address.clear();
171 182
172 backoff_amount++; 183 SetStatusMessage("Disconnected from game.");
184 }
185
186 break;
187 }
173 188
174 // If Connect is called right before this block, we will see and handle 189 // If Connect is called right before this block, we will see and handle
175 // should_disconnect. If it is called right after, and the connection 190 // should_disconnect. If it is called right after, and the connection
@@ -236,6 +251,8 @@ struct IPCState {
236 [this](const std::string& s) { OnError(s); }); 251 [this](const std::string& s) { OnError(s); });
237 return true; 252 return true;
238 } catch (const std::exception& ex) { 253 } catch (const std::exception& ex) {
254 TrackerLog(fmt::format("Error connecting to Lingo: {}", ex.what()));
255 wxMessageBox(ex.what(), "Error connecting to Lingo", wxOK | wxICON_ERROR);
239 ws.reset(); 256 ws.reset();
240 return false; 257 return false;
241 } 258 }
@@ -303,26 +320,23 @@ struct IPCState {
303 320
304 void OnError(const std::string& s) {} 321 void OnError(const std::string& s) {}
305 322
323 // Assumes mutex is locked.
306 void CheckIfSlotMatches() { 324 void CheckIfSlotMatches() {
307 slot_matches = (tracker_ap_server == game_ap_server && 325 slot_matches = (tracker_ap_server == game_ap_server &&
308 tracker_ap_user == game_ap_user); 326 tracker_ap_user == game_ap_user);
309 327
310 if (slot_matches) { 328 if (slot_matches) {
311 status_message = "Connected to game."; 329 SetStatusMessage("Connected to game.");
312 330
313 Sync(); 331 Sync();
314 } else if (connected) { 332 } else if (connected) {
315 status_message = "Local game doesn't match AP slot."; 333 SetStatusMessage("Local game doesn't match AP slot.");
316 } 334 }
317
318 tracker_frame->UpdateStatusMessage();
319 } 335 }
320 336
337 // Assumes mutex is locked.
321 void SetStatusMessage(std::optional<std::string> msg) { 338 void SetStatusMessage(std::optional<std::string> msg) {
322 { 339 status_message = msg;
323 std::lock_guard state_guard(state_mutex);
324 status_message = msg;
325 }
326 340
327 tracker_frame->UpdateStatusMessage(); 341 tracker_frame->UpdateStatusMessage();
328 } 342 }