Move platform-specific OOM handling to functions

This commit is contained in:
Simon Sapin 2018-04-04 18:43:28 +02:00
parent 747cc74943
commit c033f1ff5f

View File

@ -224,40 +224,7 @@ unsafe impl<'a> Alloc for &'a System {
alloc_methods_based_on_global_alloc!();
fn oom(&mut self) -> ! {
use core::fmt::{self, Write};
// Print a message to stderr before aborting to assist with
// debugging. It is critical that this code does not allocate any
// memory since we are in an OOM situation. Any errors are ignored
// while printing since there's nothing we can do about them and we
// are about to exit anyways.
drop(writeln!(Stderr, "fatal runtime error: {}", AllocErr));
unsafe {
::core::intrinsics::abort();
}
struct Stderr;
impl Write for Stderr {
#[cfg(target_os = "cloudabi")]
fn write_str(&mut self, _: &str) -> fmt::Result {
// CloudABI does not have any reserved file descriptor
// numbers. We should not attempt to write to file
// descriptor #2, as it may be associated with any kind of
// resource.
Ok(())
}
#[cfg(not(target_os = "cloudabi"))]
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
libc::write(libc::STDERR_FILENO,
s.as_ptr() as *const libc::c_void,
s.len());
}
Ok(())
}
}
::oom()
}
}
@ -301,8 +268,6 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut Void {
#[cfg(windows)]
#[allow(bad_style)]
mod platform {
use core::ptr;
use MIN_ALIGN;
use System;
use core::alloc::{GlobalAlloc, Alloc, Void, AllocErr, Layout, CannotReallocInPlace};
@ -312,10 +277,6 @@ mod platform {
type SIZE_T = usize;
type DWORD = u32;
type BOOL = i32;
type LPDWORD = *mut DWORD;
type LPOVERLAPPED = *mut u8;
const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
extern "system" {
fn GetProcessHeap() -> HANDLE;
@ -323,20 +284,12 @@ mod platform {
fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
fn GetLastError() -> DWORD;
fn WriteFile(hFile: HANDLE,
lpBuffer: LPVOID,
nNumberOfBytesToWrite: DWORD,
lpNumberOfBytesWritten: LPDWORD,
lpOverlapped: LPOVERLAPPED)
-> BOOL;
fn GetStdHandle(which: DWORD) -> HANDLE;
}
#[repr(C)]
struct Header(*mut u8);
const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
&mut *(ptr as *mut Header).offset(-1)
@ -438,31 +391,7 @@ unsafe fn shrink_in_place(&mut self,
}
fn oom(&mut self) -> ! {
use core::fmt::{self, Write};
// Same as with unix we ignore all errors here
drop(writeln!(Stderr, "fatal runtime error: {}", AllocErr));
unsafe {
::core::intrinsics::abort();
}
struct Stderr;
impl Write for Stderr {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
// WriteFile silently fails if it is passed an invalid
// handle, so there is no need to check the result of
// GetStdHandle.
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
s.as_ptr() as LPVOID,
s.len() as DWORD,
ptr::null_mut(),
ptr::null_mut());
}
Ok(())
}
}
::oom()
}
}
}
@ -522,3 +451,59 @@ unsafe impl<'a> Alloc for &'a System {
alloc_methods_based_on_global_alloc!();
}
}
fn oom() -> ! {
write_to_stderr("fatal runtime error: memory allocation failed");
unsafe {
::core::intrinsics::abort();
}
}
#[cfg(any(unix, target_os = "redox"))]
fn write_to_stderr(s: &str) {
extern crate libc;
unsafe {
libc::write(libc::STDERR_FILENO,
s.as_ptr() as *const libc::c_void,
s.len());
}
}
#[cfg(windows)]
fn write_to_stderr(s: &str) {
use core::ptr;
type LPVOID = *mut u8;
type HANDLE = LPVOID;
type DWORD = u32;
type BOOL = i32;
type LPDWORD = *mut DWORD;
type LPOVERLAPPED = *mut u8;
const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
extern "system" {
fn WriteFile(hFile: HANDLE,
lpBuffer: LPVOID,
nNumberOfBytesToWrite: DWORD,
lpNumberOfBytesWritten: LPDWORD,
lpOverlapped: LPOVERLAPPED)
-> BOOL;
fn GetStdHandle(which: DWORD) -> HANDLE;
}
unsafe {
// WriteFile silently fails if it is passed an invalid
// handle, so there is no need to check the result of
// GetStdHandle.
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
s.as_ptr() as LPVOID,
s.len() as DWORD,
ptr::null_mut(),
ptr::null_mut());
}
}
#[cfg(not(any(windows, unix, target_os = "redox")))]
fn write_to_stderr(_: &str) {}