Fix application crash on WiFi page

This commit is contained in:
NeilClack
2026-08-13 13:27:57 -05:00
parent bc165ef40f
commit bea9a86358
2 changed files with 37 additions and 8 deletions
+35 -7
View File
@@ -3,6 +3,7 @@
#include "provisioning.h" #include "provisioning.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <algorithm> #include <algorithm>
#include <exception>
#include <iostream> #include <iostream>
void WiFiSetupPage::onPush(AppState& state) { void WiFiSetupPage::onPush(AppState& state) {
@@ -123,6 +124,17 @@ void WiFiSetupPage::refreshNetworkState() {
savedSsids_ = state_->network.savedNetworks(); savedSsids_ = state_->network.savedNetworks();
networks_ = state_->network.getScanResults(); networks_ = state_->network.getScanResults();
if (inputMode_ != InputMode::Normal && !selectedSsid_.empty()) {
// Pin the selection to the SSID while a password is being entered or a
// connection is in progress, so list reordering (strength changes,
// APs appearing/vanishing) cannot silently switch the target network.
auto it = std::find_if(networks_.begin(), networks_.end(),
[this](const radiantwave::network::NetworkInfo& n) { return n.ssid == selectedSsid_; });
if (it != networks_.end()) {
selectedIndex_ = static_cast<int>(std::distance(networks_.begin(), it));
}
}
if (selectedIndex_ >= static_cast<int>(networks_.size())) { if (selectedIndex_ >= static_cast<int>(networks_.size())) {
selectedIndex_ = std::max(0, static_cast<int>(networks_.size()) - 1); selectedIndex_ = std::max(0, static_cast<int>(networks_.size()) - 1);
} }
@@ -136,7 +148,15 @@ void WiFiSetupPage::startConnectAsync(const std::string& ssid, const std::string
statusMessage_ = "Connecting to " + ssid + "..."; statusMessage_ = "Connecting to " + ssid + "...";
connectFuture_ = std::async(std::launch::async, [this, ssid, password]() { connectFuture_ = std::async(std::launch::async, [this, ssid, password]() {
// Never let an exception escape the worker thread — a transient
// D-Bus failure must surface as a graceful connection error, not a
// crash when update() calls future.get().
try {
return state_->network.connect(ssid, password); return state_->network.connect(ssid, password);
} catch (const std::exception& e) {
return radiantwave::network::ConnectResult{
radiantwave::network::ConnectionState::Failed, e.what(), ""};
}
}); });
} }
@@ -158,9 +178,8 @@ void WiFiSetupPage::handleEvent(const SDL_Event& event) {
if (state_->window) { if (state_->window) {
SDL_StopTextInput(state_->window); SDL_StopTextInput(state_->window);
} }
if (selectedIndex_ >= 0 && selectedIndex_ < static_cast<int>(networks_.size())) { if (!selectedSsid_.empty()) {
std::string ssid = networks_[selectedIndex_].ssid; startConnectAsync(selectedSsid_, passwordInput_);
startConnectAsync(ssid, passwordInput_);
} }
} else if (event.key.key == SDLK_ESCAPE) { } else if (event.key.key == SDLK_ESCAPE) {
if (state_->window) { if (state_->window) {
@@ -190,6 +209,7 @@ void WiFiSetupPage::handleEvent(const SDL_Event& event) {
if (net.security == radiantwave::network::SecurityType::Open) { if (net.security == radiantwave::network::SecurityType::Open) {
startConnectAsync(net.ssid, ""); startConnectAsync(net.ssid, "");
} else { } else {
selectedSsid_ = net.ssid;
inputMode_ = InputMode::PasswordEntry; inputMode_ = InputMode::PasswordEntry;
passwordInput_ = ""; passwordInput_ = "";
statusMessage_ = "Type password and press ENTER to submit"; statusMessage_ = "Type password and press ENTER to submit";
@@ -256,14 +276,22 @@ void WiFiSetupPage::update(float dt) {
if (connectInProgress_ && connectFuture_.valid()) { if (connectInProgress_ && connectFuture_.valid()) {
auto status = connectFuture_.wait_for(std::chrono::milliseconds(0)); auto status = connectFuture_.wait_for(std::chrono::milliseconds(0));
if (status == std::future_status::ready) { if (status == std::future_status::ready) {
auto result = connectFuture_.get(); radiantwave::network::ConnectResult result;
try {
result = connectFuture_.get();
} catch (const std::exception& e) {
// Backstop: a stray exception must never reach the render
// loop. Convert it to a visible, non-fatal connection error.
result = radiantwave::network::ConnectResult{
radiantwave::network::ConnectionState::Failed, e.what(), ""};
}
connectInProgress_ = false; connectInProgress_ = false;
if (result.state == radiantwave::network::ConnectionState::Activated) { if (result.state == radiantwave::network::ConnectionState::Activated) {
statusMessage_ = "Connected successfully!"; statusMessage_ = "Connected successfully!";
inputMode_ = InputMode::Normal; inputMode_ = InputMode::Normal;
} else { } else {
statusMessage_ = "Connection failed: " + (result.error_message.empty() ? "Authentication or signal error" : result.error_message); statusMessage_ = "Connection failed: " + (result.error_message.empty() ? "Incorrect password or authentication error" : result.error_message);
inputMode_ = InputMode::Normal; inputMode_ = InputMode::Normal;
} }
refreshNetworkState(); refreshNetworkState();
@@ -427,8 +455,8 @@ void WiFiSetupPage::render(SDL_Renderer* renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderRect(renderer, &boxRect); SDL_RenderRect(renderer, &boxRect);
if (selectedIndex_ >= 0 && selectedIndex_ < static_cast<int>(networks_.size())) { if (!selectedSsid_.empty()) {
std::string promptStr = "Enter Password for " + networks_[selectedIndex_].ssid + ":"; std::string promptStr = "Enter Password for " + selectedSsid_ + ":";
passwordPromptText_.ensure(renderer, fontHeader_, promptStr, white); passwordPromptText_.ensure(renderer, fontHeader_, promptStr, white);
if (passwordPromptText_.texture) { if (passwordPromptText_.texture) {
SDL_FRect dst{boxX + 30.0f, boxY + 25.0f, passwordPromptText_.width, passwordPromptText_.height}; SDL_FRect dst{boxX + 30.0f, boxY + 25.0f, passwordPromptText_.width, passwordPromptText_.height};
+1
View File
@@ -37,6 +37,7 @@ private:
AppState* state_ = nullptr; AppState* state_ = nullptr;
InputMode inputMode_ = InputMode::Normal; InputMode inputMode_ = InputMode::Normal;
int selectedIndex_ = 0; int selectedIndex_ = 0;
std::string selectedSsid_ = "";
std::string passwordInput_ = ""; std::string passwordInput_ = "";
std::string statusMessage_ = "Press F5 to scan for available networks"; std::string statusMessage_ = "Press F5 to scan for available networks";