Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::ffi::OsString;
use std::path::PathBuf;

use clap::{Parser, Subcommand};
Expand Down Expand Up @@ -28,7 +27,7 @@ pub struct Cli {
pub session: bool,
/// Command to run upon compositor startup.
#[arg(last = true)]
pub command: Vec<OsString>,
pub command: Vec<String>,

#[command(subcommand)]
pub subcommand: Option<Sub>,
Expand Down
32 changes: 20 additions & 12 deletions src/utils/spawning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::os::unix::process::CommandExt;
use std::path::Path;
use std::process::{Child, Command, Stdio};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock;
use std::sync::{mpsc, RwLock};
use std::{io, thread};

use atomic::Atomic;
Expand Down Expand Up @@ -63,24 +63,32 @@ pub fn restore_nofile_rlimit() {
}

/// Spawns the command to run independently of the compositor.
pub fn spawn<T: AsRef<OsStr> + Send + 'static>(command: Vec<T>, token: Option<XdgActivationToken>) {
pub fn spawn(command: Vec<String>, token: Option<XdgActivationToken>) {
let _span = tracy_client::span!();

if command.is_empty() {
return;
}

// Spawning and waiting takes some milliseconds, so do it in a thread.
let res = thread::Builder::new()
.name("Command Spawner".to_owned())
.spawn(move || {
let (command, args) = command.split_first().unwrap();
spawn_sync(command, args, token);
type Message = (Vec<String>, Option<XdgActivationToken>);
static SPAWNING_CHANNEL: std::sync::LazyLock<mpsc::SyncSender<Message>> =
std::sync::LazyLock::new(|| {
let (sender, receiver) = mpsc::sync_channel::<Message>(16);
thread::Builder::new()
.name("Command Spawner".to_owned())
.stack_size(96 * 1024)
.spawn(move || {
for (command, token) in receiver.into_iter() {
let (command, args) = command.split_first().unwrap();
spawn_sync(command, args, token);
}
})
.unwrap();
sender
});

if let Err(err) = res {
warn!("error spawning a thread to spawn the command: {err:?}");
}
if let Err(err) = SPAWNING_CHANNEL.send((command, token)) {
warn!("error sending command to the spawning thread: {err:?}");
};
}

/// Spawns the command through the shell.
Expand Down