GJS开发的GNOME Shell VPN扩展休眠唤醒后状态不同步问题求助
GJS VPN扩展休眠唤醒后状态不同步解决方案
问题根因
当前扩展的VPN状态完全依赖openconnect进程的标准输出事件触发同步,系统进入休眠时,GIO的异步流读取会被中断,唤醒后不会自动恢复监听。即使openconnect进程实际仍在运行,扩展也无法收到事件更新状态,而你现有的pidof校验逻辑仅在扩展初始化时执行一次,唤醒后不会自动触发,因此出现状态不一致的问题。
解决方案
方案1:监听系统休眠唤醒信号(首选实现)
GNOME Shell提供了LoginManager接口可以直接监听系统休眠/唤醒事件,唤醒后主动同步一次状态即可解决问题,修改步骤如下:
- 导入LoginManager依赖
const LoginManager = imports.misc.loginManager;
- 在Indicator类中新增状态同步方法
_resyncState() { // 检测openconnect进程是否存活 let [, , , status] = GLib.spawn_command_line_sync('pidof openconnect'); const isConnected = status === 0; setConnectionState(isConnected); _connectionSwitch.setToggleState(isConnected); _already_running = isConnected; // 如果进程存活但之前的_proc已经失效,重置_proc避免后续断开操作失败 if (isConnected && !_proc) { _already_running = true; } }
- 在Indicator的
_init方法中绑定唤醒事件监听,同时保存信号ID方便后续销毁
// 在_init方法末尾添加以下代码 this._loginManager = LoginManager.get_default(); this._sleepSignalId = this._loginManager.connect('prepare-for-sleep', (manager, sleeping) => { // sleeping为false时表示系统刚完成唤醒 if (!sleeping) { this._resyncState(); } });
- 在Extension的
disable方法中解绑信号避免内存泄漏
disable() { // 新增:解绑休眠信号 if (this._indicator?._sleepSignalId) { this._indicator._loginManager.disconnect(this._indicator._sleepSignalId); } // 原有逻辑保持不变 _proc = null; _connectionSwitch = null; _last_connection = false; _icon.destroy(); _icon = null; this._indicator.destroy(); this._indicator = null; }
方案2:新增定时轮询兜底(可选,双保险)
如果担心唤醒信号漏触发,可以增加一个低频率的定时轮询,定期同步状态,对性能几乎无影响:
- 在Indicator的
_init方法中添加定时器
this._pollTimerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 30, () => { this._resyncState(); return GLib.SOURCE_CONTINUE; });
- 在disable方法中销毁定时器
// 在disable方法中新增 if (this._indicator?._pollTimerId) { GLib.source_remove(this._indicator._pollTimerId); }
额外优化建议
你当前的create_connection脚本中vpn-ura-pke &再wait的写法可以直接简化为直接执行vpn-ura-pke,不需要后台运行再等待,避免信号传递异常的问题。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

