fix(network): async connectWifi so systemd watchdog can fire during nmcli wait
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { execSync, spawnSync } = require('child_process');
|
||||
const { execSync, spawnSync, spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const log = require('./logger');
|
||||
@@ -222,27 +222,59 @@ function nmcliSync(args, timeoutMs = 60000) {
|
||||
return (r.stdout || '').trim();
|
||||
}
|
||||
|
||||
function _delay(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/** 异步 nmcli,不阻塞事件循环(systemd Watchdog 依赖 setInterval 在主线程运行) */
|
||||
function nmcliAsync(args, timeoutMs = 60000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn('nmcli', args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
const timer = setTimeout(() => {
|
||||
child.kill('SIGKILL');
|
||||
reject(new Error('nmcli 超时'));
|
||||
}, timeoutMs);
|
||||
child.stdout.on('data', (d) => { stdout += d; });
|
||||
child.stderr.on('data', (d) => { stderr += d; });
|
||||
child.on('error', (err) => {
|
||||
clearTimeout(timer);
|
||||
reject(err);
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
clearTimeout(timer);
|
||||
if (code !== 0) {
|
||||
const msg = stderr.trim() || stdout.trim() || `nmcli exit ${code}`;
|
||||
reject(new Error(msg));
|
||||
} else {
|
||||
resolve(stdout.trim());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接指定 WiFi(配网场景:成功 = NM 显示 STA 已连上目标网,不要求一定能 ping 通 8.8.8.8)
|
||||
* @returns {{ success: boolean, error?: string }}
|
||||
* 必须异步:同步 spawnSync + execSync(sleep) 会卡住主线程,导致 systemd WatchdogSec 内收不到 WATCHDOG=1。
|
||||
* @returns {Promise<{ success: boolean, error?: string }>}
|
||||
*/
|
||||
function connectWifi(ssid, password) {
|
||||
async function connectWifi(ssid, password) {
|
||||
const iface = getWifiIface();
|
||||
log.info('network', `尝试连接 WiFi: ${ssid}(ifname=${iface})`);
|
||||
try {
|
||||
try {
|
||||
nmcliSync(['connection', 'delete', ssid], 15000);
|
||||
await nmcliAsync(['connection', 'delete', ssid], 15000);
|
||||
} catch (_) {}
|
||||
|
||||
// 关热点后部分固件需显式保证由 NM 管理、再关联
|
||||
try {
|
||||
nmcliSync(['device', 'set', iface, 'managed', 'yes'], 8000);
|
||||
await nmcliAsync(['device', 'set', iface, 'managed', 'yes'], 8000);
|
||||
} catch (_) {}
|
||||
|
||||
const args = ['device', 'wifi', 'connect', ssid];
|
||||
if (password) args.push('password', password);
|
||||
args.push('ifname', iface);
|
||||
nmcliSync(args, 120000);
|
||||
await nmcliAsync(args, 120000);
|
||||
|
||||
const deadline = Date.now() + CONNECT_WIFI_STA_WAIT_MS;
|
||||
while (Date.now() < deadline) {
|
||||
@@ -257,7 +289,7 @@ function connectWifi(ssid, password) {
|
||||
}
|
||||
return { success: true };
|
||||
}
|
||||
sleep(CONNECT_WIFI_STA_POLL_MS);
|
||||
await _delay(CONNECT_WIFI_STA_POLL_MS);
|
||||
}
|
||||
return { success: false, error: '超时:网卡未进入已连接状态' };
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user