Skip to content

Commit 3279d10

Browse files
committed
Stabilize daemon lifecycle and edge build versioning
1 parent 42c9705 commit 3279d10

7 files changed

Lines changed: 119 additions & 49 deletions

File tree

.github/workflows/build-release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ jobs:
5656
else
5757
python ./scripts/ci-sync-version.py
5858
fi
59+
echo "RELEASE_VERSION=${{ github.event.inputs.release_tag || github.ref_name }}" | sed 's/^RELEASE_VERSION=v/RELEASE_VERSION=/' >> "${GITHUB_ENV}"
60+
echo "LINUXDO_BUILD_VERSION=${{ github.event.inputs.release_tag || github.ref_name }}" | sed 's/^LINUXDO_BUILD_VERSION=v/LINUXDO_BUILD_VERSION=/' >> "${GITHUB_ENV}"
5961
6062
- uses: dtolnay/rust-toolchain@stable
6163

@@ -144,6 +146,8 @@ jobs:
144146
else
145147
python ./scripts/ci-sync-version.py
146148
fi
149+
echo "RELEASE_VERSION=${{ github.event.inputs.release_tag || github.ref_name }}" | sed 's/^RELEASE_VERSION=v/RELEASE_VERSION=/' >> "${GITHUB_ENV}"
150+
echo "LINUXDO_BUILD_VERSION=${{ github.event.inputs.release_tag || github.ref_name }}" | sed 's/^LINUXDO_BUILD_VERSION=v/LINUXDO_BUILD_VERSION=/' >> "${GITHUB_ENV}"
147151
148152
- uses: actions/setup-java@v4
149153
with:

.github/workflows/publish-edge-pre-release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ jobs:
7070
RELEASE_VERSION="${base_version}-edge.${GITHUB_RUN_NUMBER}" \
7171
ANDROID_VERSION_SERIAL="${build_serial}" \
7272
"$PYTHON_BIN" ./scripts/ci-sync-version.py
73+
echo "RELEASE_VERSION=${base_version}-edge.${GITHUB_RUN_NUMBER}" >> "${GITHUB_ENV}"
74+
echo "LINUXDO_BUILD_VERSION=${base_version}-edge.${GITHUB_RUN_NUMBER}" >> "${GITHUB_ENV}"
7375
7476
- uses: dtolnay/rust-toolchain@stable
7577

@@ -170,6 +172,8 @@ jobs:
170172
RELEASE_VERSION="${base_version}-edge.${GITHUB_RUN_NUMBER}" \
171173
ANDROID_VERSION_SERIAL="${build_serial}" \
172174
"$PYTHON_BIN" ./scripts/ci-sync-version.py
175+
echo "RELEASE_VERSION=${base_version}-edge.${GITHUB_RUN_NUMBER}" >> "${GITHUB_ENV}"
176+
echo "LINUXDO_BUILD_VERSION=${base_version}-edge.${GITHUB_RUN_NUMBER}" >> "${GITHUB_ENV}"
173177
174178
- uses: actions/setup-java@v4
175179
with:

build.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
fn main() {
22
println!("cargo:rerun-if-changed=assets/icons/linuxdo.ico");
3+
println!("cargo:rerun-if-env-changed=LINUXDO_BUILD_VERSION");
4+
println!("cargo:rerun-if-env-changed=RELEASE_VERSION");
5+
6+
let build_version = std::env::var("LINUXDO_BUILD_VERSION")
7+
.ok()
8+
.filter(|value| !value.trim().is_empty())
9+
.or_else(|| {
10+
std::env::var("RELEASE_VERSION")
11+
.ok()
12+
.filter(|value| !value.trim().is_empty())
13+
})
14+
.or_else(|| {
15+
std::env::var("CARGO_PKG_VERSION")
16+
.ok()
17+
.filter(|value| !value.trim().is_empty())
18+
})
19+
.unwrap_or_else(|| "0.0.0".to_string());
20+
println!("cargo:rustc-env=LINUXDO_BUILD_VERSION={build_version}");
321

422
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
523
let mut res = winresource::WindowsResource::new();

src/gui.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ use crate::state::{self, ServiceState};
3535

3636
const APP_WINDOW_TITLE: &str = "Linux.do Accelerator";
3737
const APP_ID: &str = "linuxdo-accelerator";
38-
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
38+
const APP_VERSION: &str = match option_env!("LINUXDO_BUILD_VERSION") {
39+
Some(version) => version,
40+
None => env!("CARGO_PKG_VERSION"),
41+
};
3942
const ACTIVE_REPAINT_INTERVAL: Duration = Duration::from_millis(100);
4043
const IDLE_REPAINT_INTERVAL: Duration = Duration::from_secs(5);
4144
const TRAY_REPAINT_INTERVAL: Duration = Duration::from_secs(15);
@@ -1624,7 +1627,6 @@ impl AcceleratorApp {
16241627
}
16251628
}
16261629

1627-
16281630
#[cfg(target_os = "windows")]
16291631
fn restore_from_tray(&mut self, ctx: &egui::Context) {
16301632
self.hidden_to_tray = false;
@@ -2719,7 +2721,7 @@ fn schedule_windows_shortcut_icon_refresh(config_path: &Path) {
27192721
.with_context(|| format!("failed to create {}", paths.runtime_dir.display()))?;
27202722

27212723
let stamp_path = paths.runtime_dir.join("windows-shortcut-icon-sync.txt");
2722-
let stamp = format!("{}\n{}", env!("CARGO_PKG_VERSION"), current_exe.display());
2724+
let stamp = format!("{}\n{}", APP_VERSION, current_exe.display());
27232725
if std::fs::read_to_string(&stamp_path).ok().as_deref() == Some(stamp.as_str()) {
27242726
return Ok(());
27252727
}

src/proxy.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ pub async fn run_proxy(
155155
Ok(())
156156
}
157157

158-
async fn run_http_redirect(state: Arc<AppState>, mut shutdown_rx: watch::Receiver<bool>) -> Result<()> {
158+
async fn run_http_redirect(
159+
state: Arc<AppState>,
160+
mut shutdown_rx: watch::Receiver<bool>,
161+
) -> Result<()> {
159162
let address = format!("{}:{}", state.config.listen_host, state.config.http_port);
160163
let listener = TcpListener::bind(&address)
161164
.await
@@ -398,7 +401,11 @@ async fn dispatch_upstream_request(
398401
path_and_query,
399402
&format!(
400403
"attempt addr={addr} scheme={upstream_scheme} ech={} edge_node={}",
401-
if upstream.ech_config.is_some() { "yes" } else { "no" },
404+
if upstream.ech_config.is_some() {
405+
"yes"
406+
} else {
407+
"no"
408+
},
402409
state
403410
.config
404411
.edge_node_override()
@@ -633,7 +640,11 @@ async fn resolve_upstream(state: &AppState, host: &str, port: u16) -> Result<Res
633640
&format!(
634641
"resolve cache-hit addrs={} ech={}",
635642
format_socket_addrs(&cached.addrs),
636-
if cached.ech_config.is_some() { "yes" } else { "no" }
643+
if cached.ech_config.is_some() {
644+
"yes"
645+
} else {
646+
"no"
647+
}
637648
),
638649
);
639650
return Ok(cached);
@@ -689,8 +700,7 @@ async fn resolve_upstream(state: &AppState, host: &str, port: u16) -> Result<Res
689700
}
690701
Ok((Vec::new(), None))
691702
};
692-
let ((mut ips, addr_ttl), (extra_ips, extra_ttl)) = if let Some(edge_override) = edge_override
693-
{
703+
let ((mut ips, addr_ttl), (extra_ips, extra_ttl)) = if let Some(edge_override) = edge_override {
694704
let override_lookup = async {
695705
match edge_override {
696706
DnsHostOverride::Addresses(ips) => Ok((ips, None)),
@@ -743,7 +753,11 @@ async fn resolve_upstream(state: &AppState, host: &str, port: u16) -> Result<Res
743753
&format!(
744754
"resolve binding_host={binding_host} target_host={target_host} addrs={} ech={} edge_node={}",
745755
format_socket_addrs(&upstream.addrs),
746-
if upstream.ech_config.is_some() { "yes" } else { "no" },
756+
if upstream.ech_config.is_some() {
757+
"yes"
758+
} else {
759+
"no"
760+
},
747761
state
748762
.config
749763
.edge_node_override()
@@ -1281,16 +1295,16 @@ fn extract_host(headers: &HeaderMap, uri: &http::Uri, config: &AppConfig) -> Opt
12811295
uri.authority()
12821296
.map(|authority| authority.host().to_ascii_lowercase())
12831297
.or_else(|| {
1284-
headers
1285-
.get(HOST)
1286-
.and_then(|value| value.to_str().ok())
1287-
.map(|value| {
1288-
value
1289-
.split(':')
1290-
.next()
1291-
.unwrap_or(value)
1292-
.to_ascii_lowercase()
1293-
})
1298+
headers
1299+
.get(HOST)
1300+
.and_then(|value| value.to_str().ok())
1301+
.map(|value| {
1302+
value
1303+
.split(':')
1304+
.next()
1305+
.unwrap_or(value)
1306+
.to_ascii_lowercase()
1307+
})
12941308
})
12951309
.or_else(|| config.proxy_domains.first().cloned())
12961310
}

src/service.rs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::net::{TcpStream, ToSocketAddrs};
22
use std::path::PathBuf;
3+
#[cfg(target_family = "unix")]
34
use std::process::Command;
45
use std::sync::Arc;
56
use std::sync::atomic::{AtomicBool, Ordering};
@@ -105,11 +106,7 @@ pub async fn run_foreground(config_path: Option<PathBuf>, with_setup: bool) -> R
105106
state::mark_running(&paths, pid)?;
106107
let ui_managed_shutdown = Arc::new(AtomicBool::new(false));
107108
let (shutdown_tx, shutdown_rx) = watch::channel(false);
108-
let watchdog = spawn_ui_lease_watchdog(
109-
paths.clone(),
110-
ui_managed_shutdown.clone(),
111-
shutdown_tx,
112-
);
109+
let watchdog = spawn_ui_lease_watchdog(paths.clone(), ui_managed_shutdown.clone(), shutdown_tx);
113110
let result = run_proxy(config.clone(), paths.clone(), bundle, shutdown_rx).await;
114111
watchdog.abort();
115112
let _ = state::clear_pid_if_matches(&paths, pid);
@@ -193,9 +190,7 @@ pub fn helper_start(config_path: Option<PathBuf>) -> Result<()> {
193190
log_warn(
194191
&paths,
195192
"helper-start",
196-
&format!(
197-
"启动流程报告异常,但检测到现有服务仍在运行,已修复状态:{error:#}"
198-
),
193+
&format!("启动流程报告异常,但检测到现有服务仍在运行,已修复状态:{error:#}"),
199194
);
200195
return Ok(());
201196
}
@@ -466,6 +461,7 @@ fn wait_until_running(paths: &AppPaths, config: &AppConfig, timeout: Duration) -
466461
bail!("daemon start timed out")
467462
}
468463

464+
#[cfg_attr(not(target_family = "unix"), allow(unused_variables))]
469465
fn discover_running_daemon_pid(paths: &AppPaths) -> Option<u32> {
470466
#[cfg(target_family = "unix")]
471467
{
@@ -727,8 +723,18 @@ fn spawn_ui_lease_watchdog(
727723
shutdown_tx: watch::Sender<bool>,
728724
) -> tokio::task::JoinHandle<()> {
729725
tokio::spawn(async move {
730-
if state::read_ui_lease(&paths).ok().flatten().is_none() {
731-
return;
726+
match state::read_ui_lease(&paths) {
727+
Ok(Some(_)) => {}
728+
Ok(None) => return,
729+
Err(error) => {
730+
let _ = runtime_log::append(
731+
&paths,
732+
"WARN",
733+
"ui-watchdog",
734+
&format!("failed to read initial ui lease state: {error:#}"),
735+
);
736+
return;
737+
}
732738
}
733739
let stale_after = Duration::from_secs(8);
734740
let mut missing_since: Option<u64> = None;
@@ -739,31 +745,43 @@ fn spawn_ui_lease_watchdog(
739745
.duration_since(UNIX_EPOCH)
740746
.map(|duration| duration.as_secs())
741747
.unwrap_or(0);
742-
let Some(lease) = state::read_ui_lease(&paths).ok().flatten() else {
743-
let first_missing_at = *missing_since.get_or_insert(now);
744-
let missing_for = now.saturating_sub(first_missing_at);
745-
if missing_for < stale_after.as_secs() {
748+
let lease = match state::read_ui_lease(&paths) {
749+
Ok(Some(lease)) => lease,
750+
Ok(None) => {
751+
let first_missing_at = *missing_since.get_or_insert(now);
752+
let missing_for = now.saturating_sub(first_missing_at);
753+
if missing_for < stale_after.as_secs() {
754+
continue;
755+
}
756+
ui_managed_shutdown.store(true, Ordering::SeqCst);
757+
let _ = runtime_log::append(
758+
&paths,
759+
"WARN",
760+
"ui-watchdog",
761+
&format!(
762+
"ui lease missing for {}s while daemon is ui-managed; requesting shutdown",
763+
missing_for
764+
),
765+
);
766+
let _ = shutdown_tx.send(true);
767+
break;
768+
}
769+
Err(error) => {
770+
let _ = runtime_log::append(
771+
&paths,
772+
"WARN",
773+
"ui-watchdog",
774+
&format!("failed to read ui lease state, keeping daemon alive: {error:#}"),
775+
);
746776
continue;
747777
}
748-
ui_managed_shutdown.store(true, Ordering::SeqCst);
749-
let _ = runtime_log::append(
750-
&paths,
751-
"WARN",
752-
"ui-watchdog",
753-
&format!(
754-
"ui lease missing for {}s while daemon is ui-managed; requesting shutdown",
755-
missing_for
756-
),
757-
);
758-
let _ = shutdown_tx.send(true);
759-
break;
760778
};
761779
missing_since = None;
762780

763781
let now = now.max(lease.updated_at);
764782
let stale = now.saturating_sub(lease.updated_at) >= stale_after.as_secs();
765-
let owner_dead = !is_process_running(lease.owner_pid);
766-
if stale || owner_dead {
783+
if stale {
784+
let owner_dead = !is_process_running(lease.owner_pid);
767785
ui_managed_shutdown.store(true, Ordering::SeqCst);
768786
let _ = runtime_log::append(
769787
&paths,

src/state.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,11 @@ fn replace_file(path: &Path, content: &[u8]) -> Result<()> {
234234
.with_context(|| format!("failed to write {}", tmp_path.display()))?;
235235

236236
move_file_replace(&tmp_path, path).with_context(|| {
237-
format!("failed to move {} to {}", tmp_path.display(), path.display())
237+
format!(
238+
"failed to move {} to {}",
239+
tmp_path.display(),
240+
path.display()
241+
)
238242
})?;
239243
Ok(())
240244
}
@@ -243,7 +247,13 @@ fn replace_file(path: &Path, content: &[u8]) -> Result<()> {
243247
fn move_file_replace(src: &Path, dst: &Path) -> Result<()> {
244248
let src_wide: Vec<u16> = src.as_os_str().encode_wide().chain(Some(0)).collect();
245249
let dst_wide: Vec<u16> = dst.as_os_str().encode_wide().chain(Some(0)).collect();
246-
let ok = unsafe { MoveFileExW(src_wide.as_ptr(), dst_wide.as_ptr(), MOVEFILE_REPLACE_EXISTING) };
250+
let ok = unsafe {
251+
MoveFileExW(
252+
src_wide.as_ptr(),
253+
dst_wide.as_ptr(),
254+
MOVEFILE_REPLACE_EXISTING,
255+
)
256+
};
247257
if ok == 0 {
248258
return Err(std::io::Error::last_os_error()).context("MoveFileExW failed");
249259
}

0 commit comments

Comments
 (0)