about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--corgi/src/caller.rs29
-rw-r--r--parrot_module/src/lib.rs18
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<CgiResponse>) {
 	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<HandleFn> = lib.get(b"handle").unwrap();
-		let free: libloading::Symbol<FreeFn> = lib.get(b"free").unwrap();
+		let handle: libloading::Symbol<HandleFn> = lib.get(b"cgi_handle").unwrap();
+		let free: libloading::Symbol<CleanupFn> = 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::<ModuleResponse>::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);
 }