Skip to content

Commit

Permalink
replace fork with posix_spawn
Browse files Browse the repository at this point in the history
  • Loading branch information
doriancodes committed Dec 18, 2024
1 parent a9d5e03 commit f2a1c4d
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 45 deletions.
23 changes: 23 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use froggr::modules::namespace::BindMode;
use froggr::modules::session::SessionManager;
use log::{debug, error, info};
use std::path::PathBuf;
use froggr::session::Session;
use std::path::Path;
use env_logger;
use nix::unistd::mkfifo;
use nix::sys::stat::Mode;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
Expand Down Expand Up @@ -62,6 +66,12 @@ enum Commands {
/// Session ID (required for kill and show operations)
session_id: Option<String>,
},
/// Internal command for running a session process
#[clap(hide = true)]
InternalSession {
session_id: String,
root: PathBuf,
},
}

#[tokio::main]
Expand Down Expand Up @@ -169,6 +179,19 @@ async fn main() -> Result<()> {
}
}
}
Commands::InternalSession { session_id, root } => {
info!("Starting session process for ID: {}", session_id);
let pipe_path = format!("/tmp/froggr/sessions/{}.pipe", session_id);
let pipe_path = Path::new(&pipe_path);
if !pipe_path.exists() {
mkfifo(pipe_path, Mode::S_IRWXU)?;
}

// Run command listener loop
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
}

Ok(())
Expand Down
118 changes: 73 additions & 45 deletions src/modules/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use nix::unistd::Pid;
use tokio::signal::ctrl_c;
use parking_lot::RwLock;
use crate::BindMode;
use nix::libc::{posix_spawn, posix_spawnattr_t, posix_spawn_file_actions_t};
use std::ffi::CString;

/// Information about a running filesystem session.
#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -96,54 +98,80 @@ impl SessionManager {
let session_id = Uuid::new_v4().to_string();
info!("Generated new session ID: {}", session_id);

info!("Attempting to fork process...");
let fork_result = unsafe { fork() };
info!("Fork completed");
// Prepare arguments for the new process
let program = CString::new(std::env::current_exe()?.to_str().unwrap())?;
let mut args = vec![
CString::new(program.to_str().unwrap())?,
CString::new("internal-session")?,
CString::new(session_id.as_str())?,
CString::new(root.to_str().unwrap())?
];

match fork_result {
Ok(ForkResult::Parent { child }) => {
info!("In parent process. Child PID: {}", child);
let session_info = SessionInfo {
id: session_id.clone(),
pid: child.as_raw(),
root: root.clone(),
mounts: Vec::new(),
binds: Vec::new(),
};

let session_file = self.sessions_dir.join(&session_id);
info!("Saving session info to: {}", session_file.display());
match fs::write(&session_file, serde_json::to_string(&session_info)?) {
Ok(_) => info!("Session info saved successfully"),
Err(e) => error!("Failed to save session info: {}", e),
}

info!("Parent process completed successfully");
Ok(session_id)
}
Ok(ForkResult::Child) => {
info!("In child process");

// Create the pipe immediately
let pipe_path = self.sessions_dir.join(format!("{}.pipe", session_id));
info!("Creating pipe at: {}", pipe_path.display());
if !pipe_path.exists() {
match nix::unistd::mkfifo(&pipe_path, nix::sys::stat::Mode::S_IRWXU) {
Ok(_) => info!("Pipe created successfully"),
Err(e) => error!("Failed to create pipe: {}", e),
}
}
// Create a vector of pointers to the args
let mut arg_ptrs: Vec<*mut libc::c_char> = args
.iter_mut()
.map(|arg| arg.as_ptr() as *mut libc::c_char)
.collect();
arg_ptrs.push(std::ptr::null_mut());

let mut pid: libc::pid_t = 0;
let mut attr: posix_spawnattr_t = unsafe { std::mem::zeroed() };
let mut actions: posix_spawn_file_actions_t = unsafe { std::mem::zeroed() };

// Initialize the attributes
unsafe {
libc::posix_spawnattr_init(&mut attr);

// Set flags to make the process independent
let flags: libc::c_short = libc::POSIX_SPAWN_SETPGROUP as libc::c_short; // Convert to correct type
libc::posix_spawnattr_setflags(&mut attr, flags);

// Set process group ID to 0 to create new group
libc::posix_spawnattr_setpgroup(&mut attr, 0);
}

info!("Spawning new process...");
let result = unsafe {
posix_spawn(
&mut pid,
program.as_ptr(),
&actions,
&attr,
arg_ptrs.as_ptr(),
std::ptr::null()
)
};

// Clean up
unsafe {
libc::posix_spawnattr_destroy(&mut attr);
libc::posix_spawn_file_actions_destroy(&mut actions);
}

info!("Child process entering main loop");
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
Err(e) => {
error!("Fork failed with error: {}", e);
Err(anyhow::anyhow!("Fork failed: {}", e))
}
if result != 0 {
error!("posix_spawn failed with error: {}", result);
return Err(anyhow::anyhow!("Failed to spawn process: {}", result));
}

info!("Process spawned with PID: {}", pid);

let session_info = SessionInfo {
id: session_id.clone(),
pid,
root: root.clone(),
mounts: Vec::new(),
binds: Vec::new(),
};

let session_file = self.sessions_dir.join(&session_id);
info!("Saving session info to: {}", session_file.display());
match fs::write(&session_file, serde_json::to_string(&session_info)?) {
Ok(_) => info!("Session info saved successfully"),
Err(e) => error!("Failed to save session info: {}", e),
}

info!("Parent process completed successfully");
Ok(session_id)
}

/// Lists all active sessions.
Expand Down

0 comments on commit f2a1c4d

Please sign in to comment.