Created
January 30, 2014 05:35
-
-
Save wycats/8703114 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_escape]; | |
use std::rt::task::Task; | |
use std::rt::local::Local; | |
mod libunwind; | |
macro_rules! run( | |
($expr:expr) => ( | |
{ | |
let mut success = false; | |
let task = ~std::rt::task::Task::new(); | |
task.run(|| { $expr; success = true }); | |
success | |
} | |
); | |
($out:expr, $expr:expr) => ( | |
{ | |
let mut success = false; | |
let task = ~std::rt::task::Task::new(); | |
task.run(|| { $expr.to_out_ptr(out); success = true }); | |
success | |
} | |
); | |
) | |
macro_rules! ffi_run( | |
($code:expr, $args:expr) => { | |
{ | |
use std::cast::transmute; | |
use std::rt::local::Local; | |
use std::rt::task::Task; | |
if !Local::exists(None::<Task>) { | |
let task = ~Task::new(); | |
Local::put(task); | |
} | |
extern { | |
fn rust_try(f: extern "C" fn(*c_void, *c_void), code: *c_void, data: *c_void) -> *libunwind::_Unwind_Exception; | |
} | |
unsafe { | |
let ep = rust_try($code, transmute($args), 0 as *c_void); | |
if !ep.is_null() { | |
libunwind::_Unwind_DeleteException(ep); | |
close_task(); | |
let mut task: ~std::rt::task::Task = std::rt::local::Local::take(); | |
task.destroyed = true; | |
false | |
} else { | |
true | |
} | |
} | |
} | |
}; | |
) | |
macro_rules! ffi_fn( | |
($name:ident () -> $out:ty $expr:expr) => { | |
#[no_mangle] | |
pub extern "C" fn $name(out: *mut $out) -> bool { | |
use std::libc::c_void; | |
use std::cast::transmute; | |
struct Args { out: *mut $out }; | |
extern "C" fn code(args: *c_void, _: *c_void) { | |
unsafe { | |
let Args{ out }: Args = transmute(args); | |
$expr.to_out_ptr(out); | |
} | |
} | |
let args = Args{ out: out }; | |
ffi_run!(code, args) | |
} | |
}; | |
($name:ident ( $($param:ident : $ty:ty),+ ) -> $out:ty $expr:expr) => { | |
#[no_mangle] | |
#[allow(unused_variable)] | |
pub extern "C" fn $name<'a>( $($param : $ty ),+, out: *mut $out) -> bool { | |
use std::libc::c_void; | |
use std::cast::transmute; | |
struct Args<'a> { $($param : $ty),+, out: *mut $out }; | |
extern "C" fn code(args: *c_void, _: *c_void) { | |
unsafe { | |
let ~Args{ $($param),+, out }: ~Args = transmute(args); | |
$expr.to_out_ptr(out); | |
} | |
} | |
let args = ~Args{ $($param : $param),+, out: out }; | |
ffi_run!(code, args) | |
} | |
}; | |
($name:ident () $expr:expr) => { | |
#[no_mangle] | |
pub extern "C" fn $name() -> bool { | |
extern "C" fn code(_: *c_void, _: *c_void) { | |
$expr.to_out_ptr(out) | |
} | |
ffi_run!(code, 0 as *c_void); | |
} | |
}; | |
($name:ident ( $($param:ident : $ty:ty),+ ) $expr:expr) => { | |
#[no_mangle] | |
#[allow(unused_variable)] | |
pub extern "C" fn $name<'a>( $($param : $ty ),+) -> bool { | |
use std::libc::c_void; | |
use std::cast::transmute; | |
struct Args<'a> { $($param : $ty),+ }; | |
extern "C" fn code(args: *c_void, _: *c_void) { | |
unsafe { | |
let ~Args{ $($param),+ }: ~Args = transmute(args); | |
$expr; | |
} | |
} | |
let args = ~Args{ $($param : $param),+ }; | |
ffi_run!(code, args) | |
} | |
}; | |
) | |
pub fn close_task() { | |
use std::rt::task::LocalStorage; | |
fn close_outputs() { | |
let mut task = Local::borrow(None::<Task>); | |
let logger = task.get().logger.take(); | |
let stderr = task.get().stderr.take(); | |
let stdout = task.get().stdout.take(); | |
drop(task); | |
drop(logger); // loggers are responsible for flushing | |
match stdout { Some(mut w) => w.flush(), None => {} } | |
match stderr { Some(mut w) => w.flush(), None => {} } | |
} | |
close_outputs(); | |
let mut task = Local::borrow(None::<Task>); | |
{ | |
let task = task.get(); | |
let LocalStorage(ref mut optmap) = task.storage; | |
if optmap.is_some() { drop(optmap.take()) } | |
} | |
drop(task); | |
close_outputs(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On line 22, shouldn't that be
$expr.to_out_ptr($out);
? (I think you are "getting lucky" in your current code, in that our broken hygiene system is letting you get away with passing in a variable namedout
as the expression for$out
, and so this bug goes unnoticed.)