From f016a3d27e47076bfd367285c003478d990e08bb Mon Sep 17 00:00:00 2001 From: gennyble Date: Thu, 20 Mar 2025 10:35:01 -0500 Subject: Spawn a thread for the module --- corgi/src/caller.rs | 29 +++++++++++++++++++++-------- parrot_module/src/lib.rs | 18 ++++++++++++++---- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/corgi/src/caller.rs b/corgi/src/caller.rs index b942849..94b26aa 100644 --- a/corgi/src/caller.rs +++ b/corgi/src/caller.rs @@ -1,12 +1,17 @@ use std::{ ffi::{self, CString}, + io::Write, net::IpAddr, process::Stdio, ptr, str::FromStr, }; -use tokio::{io::AsyncWriteExt, process::Command}; +use tokio::{ + io::AsyncWriteExt, + process::Command, + sync::oneshot::{self, Receiver, Sender}, +}; use crate::{Script, ScriptKind}; @@ -154,6 +159,7 @@ fn parse_cgi_response(stdout: &[u8]) -> CgiResponse { } } +#[derive(Debug)] pub struct CgiResponse { /// The Status header of the CGI response pub status: u16, @@ -164,9 +170,9 @@ pub struct CgiResponse { } #[repr(C)] -struct ModuleRequest<'req> { +struct ModuleRequest { headers_len: ffi::c_ulong, - headers: &'req [[*const ffi::c_char; 2]], + headers: *const [[*const ffi::c_char; 2]], body_len: ffi::c_ulong, body: *const u8, } @@ -181,9 +187,16 @@ struct ModuleResponse { } type HandleFn = unsafe extern "C" fn(*const ModuleRequest) -> *const ModuleResponse; -type FreeFn = unsafe extern "C" fn(*const ModuleResponse); +type CleanupFn = unsafe extern "C" fn(*const ModuleResponse); pub async fn call_and_parse_module(script: Script, req: HttpRequest) -> CgiResponse { + let (tx, rx) = oneshot::channel(); + std::thread::spawn(move || unsafe { module_thread(script, req, tx) }); + + rx.await.unwrap() +} + +unsafe fn module_thread(script: Script, req: HttpRequest, tx: Sender) { let env = req.build_kv(); let mut headers_owned = vec![]; @@ -199,7 +212,7 @@ pub async fn call_and_parse_module(script: Script, req: HttpRequest) -> CgiRespo let modreq = ModuleRequest { headers_len: headers.len() as u64, - headers: &headers, + headers: &headers[..] as *const [[*const ffi::c_char; 2]], body_len: req.body.as_ref().map(|v| v.len()).unwrap_or(0) as u64, body: req.body.as_ref().map(|v| v.as_ptr()).unwrap_or(ptr::null()), }; @@ -212,8 +225,8 @@ pub async fn call_and_parse_module(script: Script, req: HttpRequest) -> CgiRespo unsafe { let lib = libloading::Library::new(script.filename).unwrap(); - let handle: libloading::Symbol = lib.get(b"handle").unwrap(); - let free: libloading::Symbol = lib.get(b"free").unwrap(); + let handle: libloading::Symbol = lib.get(b"cgi_handle").unwrap(); + let free: libloading::Symbol = lib.get(b"cgi_cleanup").unwrap(); let response = handle((&modreq) as *const ModuleRequest); let response_ref = response.as_ref().unwrap(); @@ -234,5 +247,5 @@ pub async fn call_and_parse_module(script: Script, req: HttpRequest) -> CgiRespo free(response); }; - cgi + tx.send(cgi).unwrap() } diff --git a/parrot_module/src/lib.rs b/parrot_module/src/lib.rs index 148f41d..38148ae 100644 --- a/parrot_module/src/lib.rs +++ b/parrot_module/src/lib.rs @@ -21,7 +21,7 @@ const HEADERS: &'static [[*const ffi::c_char; 2]] = &[[c"Content-Type".as_ptr(), c"text/plain".as_ptr()]]; #[unsafe(no_mangle)] -extern "C" fn handle(req: *const ModuleRequest) -> *const ModuleResponse { +extern "C" fn cgi_handle(req: *const ModuleRequest) -> *const ModuleResponse { let mut ret = String::new(); // unwrap is bad here @@ -31,7 +31,14 @@ extern "C" fn handle(req: *const ModuleRequest) -> *const ModuleResponse { let kvarr = reqref.headers[idx as usize]; let k = unsafe { CStr::from_ptr(kvarr[0]) }.to_string_lossy(); let v = unsafe { CStr::from_ptr(kvarr[1]) }.to_string_lossy(); - ret.push_str(&format!("{k}: {v}\n")); + + // While debugging I removed the format!() because it was SIGSEGVing + // as the String it allocated freed, and now that this is here it can stay + ret.push_str(&k); + ret.push(':'); + ret.push(' '); + ret.push_str(&v); + ret.push('\n') } let body = CString::new(ret).unwrap(); @@ -45,13 +52,16 @@ extern "C" fn handle(req: *const ModuleRequest) -> *const ModuleResponse { }; let boxed = Box::new(resp); - Box::::into_raw(boxed) } #[unsafe(no_mangle)] -extern "C" fn free(req: *const ModuleResponse) { +extern "C" fn cgi_cleanup(req: *const ModuleResponse) { // from_raw what we need to here so that these get dropped let boxed = unsafe { Box::from_raw(req as *mut ModuleResponse) }; let body = unsafe { CString::from_raw(boxed.body as *mut i8) }; + + // Explicitly calling drop here to feel good about myself + drop(body); + drop(boxed); } -- cgit 1.4.1-3-g733a5