forked from lix-project/lix
Don't leak exceptions
This commit is contained in:
parent
e6bd88878e
commit
b4edc3ca61
3 changed files with 48 additions and 9 deletions
|
@ -76,7 +76,7 @@ impl From<Error> for CppException {
|
||||||
fn from(err: Error) -> Self {
|
fn from(err: Error) -> Self {
|
||||||
match err {
|
match err {
|
||||||
Error::Foreign(ex) => ex,
|
Error::Foreign(ex) => ex,
|
||||||
_ => unsafe { make_error(&err.to_string()) },
|
_ => CppException::new(&err.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,23 @@ impl From<Error> for CppException {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CppException(*const libc::c_void); // == std::exception_ptr*
|
pub struct CppException(*const libc::c_void); // == std::exception_ptr*
|
||||||
|
|
||||||
|
impl CppException {
|
||||||
|
fn new(s: &str) -> Self {
|
||||||
|
Self(unsafe { make_error(s) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for CppException {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
destroy_error(self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[allow(improper_ctypes)] // YOLO
|
#[allow(improper_ctypes)] // YOLO
|
||||||
fn make_error(s: &str) -> CppException;
|
fn make_error(s: &str) -> *const libc::c_void;
|
||||||
|
|
||||||
|
fn destroy_error(exc: *const libc::c_void);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,14 @@
|
||||||
|
|
||||||
extern "C" std::exception_ptr * make_error(rust::StringSlice s)
|
extern "C" std::exception_ptr * make_error(rust::StringSlice s)
|
||||||
{
|
{
|
||||||
// FIXME: leak
|
|
||||||
return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size))));
|
return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void destroy_error(std::exception_ptr * ex)
|
||||||
|
{
|
||||||
|
free(ex);
|
||||||
|
}
|
||||||
|
|
||||||
namespace rust {
|
namespace rust {
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const String & s)
|
std::ostream & operator << (std::ostream & str, const String & s)
|
||||||
|
|
|
@ -152,28 +152,47 @@ struct Source
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Result
|
struct Result
|
||||||
{
|
{
|
||||||
unsigned int tag;
|
enum { Ok = 0, Err = 1, Uninit = 2 } tag;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
T data;
|
T data;
|
||||||
std::exception_ptr * exc;
|
std::exception_ptr * exc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Result() : tag(Uninit) { }; // FIXME: remove
|
||||||
|
|
||||||
|
Result(const Result &) = delete;
|
||||||
|
|
||||||
|
Result(Result && other)
|
||||||
|
: tag(other.tag)
|
||||||
|
{
|
||||||
|
other.tag = Uninit;
|
||||||
|
if (tag == Ok)
|
||||||
|
data = std::move(other.data);
|
||||||
|
else if (tag == Err)
|
||||||
|
exc = other.exc;
|
||||||
|
}
|
||||||
|
|
||||||
~Result()
|
~Result()
|
||||||
{
|
{
|
||||||
if (tag == 0)
|
if (tag == Ok)
|
||||||
data.~T();
|
data.~T();
|
||||||
else if (tag == 1)
|
else if (tag == Err)
|
||||||
// FIXME: don't leak exc
|
free(exc);
|
||||||
|
else if (tag == Uninit)
|
||||||
;
|
;
|
||||||
|
else
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rethrow the wrapped exception or return the wrapped value. */
|
/* Rethrow the wrapped exception or return the wrapped value. */
|
||||||
T unwrap()
|
T unwrap()
|
||||||
{
|
{
|
||||||
if (tag == 0)
|
if (tag == Ok) {
|
||||||
|
tag = Uninit;
|
||||||
return std::move(data);
|
return std::move(data);
|
||||||
else if (tag == 1)
|
}
|
||||||
|
else if (tag == Err)
|
||||||
std::rethrow_exception(*exc);
|
std::rethrow_exception(*exc);
|
||||||
else
|
else
|
||||||
abort();
|
abort();
|
||||||
|
|
Loading…
Reference in a new issue