`sys/fork`: Added moving arbitrary values into a stream, and moving them out of a stream again. This is for returning errors/return values from child process(es).

Fortune for comfork's current commit: Curse − 凶
master
Avril 3 years ago
parent d3d23be832
commit 8008643bb4

@ -7,6 +7,17 @@ use libc::{
setuid,
};
use std::{fmt, error};
use std::io::{
self,
Read,
Write,
};
use std::marker::Unpin;
use std::panic::{
AssertUnwindSafe,
catch_unwind,
resume_unwind,
};
use errno::Errno;
@ -27,6 +38,49 @@ pub enum ErrorKind
Pipe(pipe::ErrorKind),
}
// TODO: Add non-`sys` type: `Channel<T>`, which can be used to send/recv typed data between parent and child.
// It should leverage the two below functions: `move_*_stream()`.
/// Move a value into a stream.
///
/// This function will return `Ok` if and only if all bytes from `val` were successfully written to the stream `to`.
/// If only a subset of them were written, then the data is corrupt and that is counted as an error.
///
/// # Safety
/// The object `val` is written into the stream `to` verbatim. Its destructor is not run.
/// The object should be read verbatim from the stream with no errors or corruption before its dropped, or it will leak resources.
///
/// This function is safe, but reading from the stream into a new object is not.
///
/// ## Unpin
/// `T` should be `Unpin` in case it contains self-referrential data, as those references will no longer be valid after being moved across a stream.
// TODO: Should we expose these to the user somehow, with an unsafe helper module maybe? They could be useful.
// Or perhaps: Add the functionality to move types to/from the child/parent into the library, similar to `mpsc`.
pub(crate) fn move_write_value<T: Unpin, S: Write>(mut to: S, val: T) -> io::Result<()>
{
let bytes = unsafe {
std::slice::from_raw_parts(&val as *const T as *const u8, std::mem::size_of::<T>())
};
// Catch any panics that may happen in `write`.
let res = catch_unwind(AssertUnwindSafe(move || {
to.write_all(bytes)
}));
// Ensure this happens even if the above panics.
drop(bytes); // Make sure `bytes` isn't dangling after we move `val` into `forget()`.
std::mem::forget(val);
// Resume unwind if one occoured, if not return the value
match res {
Ok(v) => v,
Err(panic) => resume_unwind(panic),
}
}
//TODO: Counterpart to `move_write_value()`. This function should be `unsafe` as it is extermely unsafe.
pub(crate) unsafe fn move_read_value<T: Unpin, S: Read>(mut from: S) -> io::Result<T>
{
todo!()
}
/// An error in either forking or communicating with the child process during its setup.
#[derive(Debug)]
#[repr(transparent)]

Loading…
Cancel
Save