feat: plugins start on service launch

This commit is contained in:
Gabriele Musco 2024-08-20 00:15:25 +02:00
parent 781e2f4fd2
commit 01a61bc842
3 changed files with 67 additions and 16 deletions

View file

@ -43,7 +43,8 @@ use crate::{
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
},
util::file_utils::{
setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd, verify_cap_sys_nice_eip,
mark_as_executable, setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd,
verify_cap_sys_nice_eip,
},
vulkaninfo::VulkanInfo,
wivrn_dbus,
@ -80,6 +81,7 @@ pub struct App {
config: Config,
xrservice_worker: Option<JobWorker>,
autostart_worker: Option<JobWorker>,
plugins_worker: Option<JobWorker>,
restart_xrservice: bool,
build_worker: Option<JobWorker>,
profiles: Vec<Profile>,
@ -102,6 +104,7 @@ pub enum Msg {
OnServiceLog(Vec<String>),
OnServiceExit(i32),
OnAutostartExit(i32),
OnPluginsExit(i32),
OnBuildLog(Vec<String>),
OnBuildExit(i32),
ClockTicking,
@ -257,6 +260,39 @@ impl App {
autostart_worker.start();
self.autostart_worker = Some(autostart_worker);
}
let plugins_cmd = self
.config
.plugins
.values()
.filter_map(|cp| {
if cp.enabled {
if let Err(e) = mark_as_executable(&cp.exec_path) {
eprintln!("Failed to mark plugin {} as executable: {e}", cp.appid);
None
} else {
Some(format!("'{}'", cp.exec_path.to_string_lossy()))
}
} else {
None
}
})
.collect::<Vec<String>>()
.join(" & ");
if !plugins_cmd.is_empty() {
let mut jobs = VecDeque::new();
jobs.push_back(WorkerJob::new_cmd(
Some(prof.environment.clone()),
"sh".into(),
Some(vec!["-c".into(), plugins_cmd]),
));
let plugins_worker = JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows),
JobWorkerOut::Exit(code) => Msg::OnPluginsExit(code),
});
plugins_worker.start();
self.plugins_worker = Some(plugins_worker);
}
}
pub fn restore_openxr_openvr_files(&self) {
@ -285,27 +321,20 @@ impl App {
}
pub fn shutdown_xrservice(&mut self) {
if let Some(worker) = self.autostart_worker.as_ref() {
worker.stop();
if let Some(w) = self.autostart_worker.as_ref() {
w.stop();
}
if let Some(w) = self.plugins_worker.as_ref() {
w.stop();
}
self.xrservice_ready = false;
if let Some(w) = self.openxr_prober_worker.as_ref() {
w.stop();
// this can cause threads to remain hanging...
self.openxr_prober_worker = None;
}
self.set_inhibit_session(false);
if let Some(worker) = self.xrservice_worker.as_ref() {
worker.stop();
if let Some(w) = self.xrservice_worker.as_ref() {
w.stop();
}
self.libmonado = None;
self.main_view
.sender()
.emit(MainViewMsg::XRServiceActiveChanged(false, None, false));
self.debug_view
.sender()
.emit(DebugViewMsg::XRServiceActiveChanged(false));
self.xr_devices = vec![];
}
}
@ -371,6 +400,8 @@ impl AsyncComponent for App {
}
}
Msg::OnServiceExit(code) => {
self.set_inhibit_session(false);
self.xrservice_ready = false;
self.restore_openxr_openvr_files();
self.main_view
.sender()
@ -378,6 +409,8 @@ impl AsyncComponent for App {
self.debug_view
.sender()
.emit(DebugViewMsg::XRServiceActiveChanged(false));
self.libmonado = None;
self.xr_devices = vec![];
if code != 0 && code != 15 {
// 15 is SIGTERM
sender.input(Msg::OnServiceLog(vec![format!(
@ -393,6 +426,7 @@ impl AsyncComponent for App {
}
}
Msg::OnAutostartExit(_) => self.autostart_worker = None,
Msg::OnPluginsExit(_) => self.plugins_worker = None,
Msg::ClockTicking => {
self.main_view.sender().emit(MainViewMsg::ClockTicking);
let xrservice_worker_is_alive = self
@ -998,6 +1032,7 @@ impl AsyncComponent for App {
profiles,
xrservice_worker: None,
autostart_worker: None,
plugins_worker: None,
build_worker: None,
xr_devices: vec![],
restart_xrservice: false,

View file

@ -2,7 +2,7 @@ pub mod store;
mod store_detail;
mod store_row_factory;
use crate::paths::get_plugins_dir;
use crate::{paths::get_plugins_dir, util::file_utils::mark_as_executable};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
@ -41,4 +41,8 @@ impl Plugin {
pub fn is_installed(&self) -> bool {
self.exec_path().exists()
}
pub fn mark_as_executable(&self) -> anyhow::Result<()> {
mark_as_executable(&self.exec_path())
}
}

View file

@ -7,6 +7,7 @@ use nix::{
use std::{
fs::{self, copy, create_dir_all, remove_dir_all, File, OpenOptions},
io::{BufReader, BufWriter},
os::unix::fs::PermissionsExt,
path::Path,
};
use tracing::{debug, error};
@ -151,6 +152,17 @@ pub fn mount_has_nosuid(path: &Path) -> Result<bool, Errno> {
}
}
pub fn mark_as_executable(path: &Path) -> anyhow::Result<()> {
if !path.is_file() {
bail!("Path '{}' is not a file", path.to_string_lossy())
} else {
let mut perms = fs::metadata(path)?.permissions();
perms.set_mode(perms.mode() | 0o111);
fs::set_permissions(path, perms)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::mount_has_nosuid;