Skip to content

Commit e5f86d3

Browse files
committed
feat: add port conflict detection and error dialogs
- Add tauri-plugin-dialog dependency for user notifications - Implement port availability checking before starting gptme-server - Show error dialog when port 5700 is already in use - Improve process termination with better error handling and logging - Add sleep after process termination to allow cleanup
1 parent 4b99e1b commit e5f86d3

File tree

3 files changed

+190
-7
lines changed

3 files changed

+190
-7
lines changed

src-tauri/Cargo.lock

Lines changed: 131 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[package]
22
name = "gptme-tauri"
33
version = "0.1.0"
4-
description = "A Tauri App"
5-
authors = ["you"]
4+
description = "Desktop application for gptme"
5+
authors = ["Brayo", "Erik Bjäreholt"]
66
edition = "2021"
77

88
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -20,6 +20,7 @@ tauri-build = { version = "2", features = [] }
2020
[dependencies]
2121
tauri = { version = "2", features = [] }
2222
tauri-plugin-opener = "2"
23+
tauri-plugin-dialog = "2"
2324
serde = { version = "1", features = ["derive"] }
2425
serde_json = "1"
2526
tauri-plugin-shell = "2"

src-tauri/src/lib.rs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
1+
use std::net::TcpListener;
12
use std::sync::{Arc, Mutex};
23
use tauri::Manager;
4+
use tauri_plugin_dialog::{
5+
DialogExt, MessageDialogBuilder, MessageDialogButtons, MessageDialogKind,
6+
};
37
use tauri_plugin_log::{Target, TargetKind};
48
use tauri_plugin_shell::{process::CommandChild, ShellExt};
59

10+
const GPTME_SERVER_PORT: u16 = 5700;
11+
612
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
713
#[tauri::command]
814
fn greet(name: &str) -> String {
915
format!("Hello, {}! You've been greeted from Rust!", name)
1016
}
1117

18+
/// Check if a port is available
19+
fn is_port_available(port: u16) -> bool {
20+
TcpListener::bind(format!("127.0.0.1:{}", port)).is_ok()
21+
}
22+
1223
#[cfg_attr(mobile, tauri::mobile_entry_point)]
1324
pub fn run() {
1425
tauri::Builder::default()
@@ -25,6 +36,7 @@ pub fn run() {
2536
)
2637
.plugin(tauri_plugin_shell::init())
2738
.plugin(tauri_plugin_opener::init())
39+
.plugin(tauri_plugin_dialog::init())
2840
.invoke_handler(tauri::generate_handler![greet])
2941
.setup(|app| {
3042
log::info!("Starting gptme-tauri application");
@@ -37,14 +49,44 @@ pub fn run() {
3749

3850
// Spawn gptme-server with output capture
3951
tauri::async_runtime::spawn(async move {
52+
// Check if port is available before starting
53+
if !is_port_available(GPTME_SERVER_PORT) {
54+
log::error!(
55+
"Port {} is already in use. Another gptme-server instance may be running.",
56+
GPTME_SERVER_PORT
57+
);
58+
59+
// Show dialog to inform user about port conflict
60+
let message = format!(
61+
"Cannot start gptme-server because port {} is already in use.\n\n\
62+
This usually means another gptme-server instance is already running.\n\n\
63+
Please stop the existing gptme-server process and restart this application.",
64+
GPTME_SERVER_PORT
65+
);
66+
67+
MessageDialogBuilder::new(
68+
app_handle.dialog().clone(),
69+
"Port Conflict",
70+
message
71+
)
72+
.kind(MessageDialogKind::Error)
73+
.buttons(MessageDialogButtons::Ok)
74+
.show(|_result| {
75+
// Dialog closed, nothing to do
76+
});
77+
78+
return;
79+
}
80+
4081
// Determine CORS origin based on build mode
4182
let cors_origin = if cfg!(debug_assertions) {
4283
"http://localhost:5701" // Dev mode
4384
} else {
4485
"tauri://localhost" // Production mode
4586
};
4687

47-
log::info!("Starting gptme-server with CORS origin: {}", cors_origin);
88+
log::info!("Port {} is available, starting gptme-server with CORS origin: {}",
89+
GPTME_SERVER_PORT, cors_origin);
4890

4991
let sidecar_command = app_handle
5092
.shell()
@@ -121,11 +163,22 @@ pub fn run() {
121163
let child_ref = window.state::<Arc<Mutex<Option<CommandChild>>>>().clone();
122164
if let Ok(mut child) = child_ref.lock() {
123165
if let Some(process) = child.take() {
166+
log::info!("Attempting to terminate gptme-server process...");
124167
match process.kill() {
125-
Ok(_) => log::info!("gptme-server process terminated successfully"),
126-
Err(e) => log::error!("Failed to terminate gptme-server: {}", e),
168+
Ok(_) => {
169+
log::info!("gptme-server process terminated successfully");
170+
// Give the process a moment to cleanup
171+
std::thread::sleep(std::time::Duration::from_millis(100));
172+
},
173+
Err(e) => {
174+
log::error!("Failed to terminate gptme-server: {}", e);
175+
}
127176
}
177+
} else {
178+
log::warn!("No gptme-server process found to terminate");
128179
}
180+
} else {
181+
log::error!("Failed to acquire lock on child process reference");
129182
};
130183
}
131184
}

0 commit comments

Comments
 (0)