use fexecve on linux

This commit is contained in:
Folkert 2022-05-22 22:38:51 +02:00
parent b80b59125e
commit 0fd382e713
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 45 additions and 17 deletions

View file

@ -511,11 +511,12 @@ fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
) -> io::Result<i32> { ) -> io::Result<i32> {
match triple.architecture { match triple.architecture {
Architecture::Wasm32 => { Architecture::Wasm32 => {
let path = roc_run_executable_file_path(cwd, binary_bytes)?; let executable = roc_run_executable_file_path(cwd, binary_bytes)?;
let path = executable.as_path();
// If possible, report the generated executable name relative to the current dir. // If possible, report the generated executable name relative to the current dir.
let generated_filename = path let generated_filename = path
.strip_prefix(env::current_dir().unwrap()) .strip_prefix(env::current_dir().unwrap())
.unwrap_or(&path); .unwrap_or(path);
// No need to waste time freeing this memory, // No need to waste time freeing this memory,
// since the process is about to exit anyway. // since the process is about to exit anyway.
@ -561,7 +562,8 @@ fn roc_run_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
unsafe { unsafe {
let path = roc_run_executable_file_path(cwd, binary_bytes)?; let executable = roc_run_executable_file_path(cwd, binary_bytes)?;
let path = executable.as_path();
let path_cstring = CString::new(path.as_os_str().as_bytes()).unwrap(); let path_cstring = CString::new(path.as_os_str().as_bytes()).unwrap();
// argv is an array of pointers to strings passed to the new program // argv is an array of pointers to strings passed to the new program
@ -589,10 +591,18 @@ fn roc_run_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
// program. The envp array must be terminated by a NULL pointer. // program. The envp array must be terminated by a NULL pointer.
let envp = &[std::ptr::null()]; let envp = &[std::ptr::null()];
let execve_result = match executable {
libc::execve(path_cstring.as_ptr().cast(), argv.as_ptr(), envp.as_ptr()); ExecutableFile::MemFd(fd, _) => {
if libc::fexecve(fd, argv.as_ptr(), envp.as_ptr()) != 0 {
if execve_result != 0 { internal_error!(
"libc::fexecve({:?}, ..., ...) failed: {:?}",
path,
errno::errno()
);
}
}
ExecutableFile::OnDisk(_) => {
if libc::execve(path_cstring.as_ptr().cast(), argv.as_ptr(), envp.as_ptr()) != 0 {
internal_error!( internal_error!(
"libc::execve({:?}, ..., ...) failed: {:?}", "libc::execve({:?}, ..., ...) failed: {:?}",
path, path,
@ -600,11 +610,31 @@ fn roc_run_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
); );
} }
} }
}
}
Ok(1) Ok(1)
} }
fn roc_run_executable_file_path(cwd: &Path, binary_bytes: &mut [u8]) -> std::io::Result<PathBuf> { #[derive(Debug, Clone)]
enum ExecutableFile {
MemFd(libc::c_int, PathBuf),
OnDisk(PathBuf),
}
impl ExecutableFile {
fn as_path(&self) -> &Path {
match self {
ExecutableFile::MemFd(_, path_buf) => path_buf.as_ref(),
ExecutableFile::OnDisk(path_buf) => path_buf.as_ref(),
}
}
}
fn roc_run_executable_file_path(
cwd: &Path,
binary_bytes: &mut [u8],
) -> std::io::Result<ExecutableFile> {
if cfg!(target_os = "linux") { if cfg!(target_os = "linux") {
// on linux, we use the `memfd_create` function to create an in-memory anonymous file. // on linux, we use the `memfd_create` function to create an in-memory anonymous file.
let flags = 0; let flags = 0;
@ -623,7 +653,7 @@ fn roc_run_executable_file_path(cwd: &Path, binary_bytes: &mut [u8]) -> std::io:
std::fs::write(&path, binary_bytes)?; std::fs::write(&path, binary_bytes)?;
Ok(path) Ok(ExecutableFile::MemFd(fd, path))
} else { } else {
// we have not found a way yet to use a virtual file on MacOs. Hence we fall back to just // we have not found a way yet to use a virtual file on MacOs. Hence we fall back to just
// writing the file to the file system, and using that file. // writing the file to the file system, and using that file.
@ -631,7 +661,7 @@ fn roc_run_executable_file_path(cwd: &Path, binary_bytes: &mut [u8]) -> std::io:
std::fs::write(&app_path_buf, binary_bytes)?; std::fs::write(&app_path_buf, binary_bytes)?;
Ok(app_path_buf) Ok(ExecutableFile::OnDisk(app_path_buf))
} }
} }

View file

@ -85,8 +85,6 @@ const Unit = extern struct {};
pub fn main() u8 { pub fn main() u8 {
const stdout = std.io.getStdOut().writer(); const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer(); const stderr = std.io.getStdErr().writer();
stdout.print("xkxkxkxkyay", .{}) catch unreachable;
// std.process.exit(0);
// start time // start time
var ts1: std.os.timespec = undefined; var ts1: std.os.timespec = undefined;