Created
April 22, 2015 09:26
-
-
Save manuels/8c264818252cabe3081c to your computer and use it in GitHub Desktop.
not-crashing-anymore.rs
This file contains hidden or 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
extern crate libc; | |
use libc::{c_short, c_int, c_void, ssize_t, size_t}; | |
use std::thread; | |
mod linux { | |
use std::os::unix::io::RawFd; | |
use libc::c_int; | |
pub fn socketpair(domain: i32, type_: i32, protocol: i32) -> Result<(RawFd, RawFd), i32> { | |
unsafe { | |
let sv: [c_int; 2] = [0, 0]; | |
let res = internal::socketpair(domain as c_int, type_ as c_int, protocol as c_int, sv.as_ptr()); | |
if res == 0 { | |
assert!(sv[0] >= 0); | |
assert!(sv[1] >= 0); | |
let SOCK_CLOEXEC = 02000000; | |
let close_on_exec = (type_ & SOCK_CLOEXEC) > 0; | |
let left = sv[0]; | |
let right = sv[1]; | |
let pair = (left, right); | |
return Ok(pair) | |
} else { | |
return Err(res as i32) | |
} | |
} | |
} | |
mod internal { | |
use libc::c_int; | |
use std::os::unix::io::RawFd; | |
extern { | |
pub fn socketpair(domain: c_int, type_: c_int, protocol: c_int, sv: *const RawFd) -> c_int; | |
} | |
} | |
} | |
mod libevent { | |
use std::os::unix::io::RawFd; | |
use libc::{c_short, c_int}; | |
use std::ptr::null; | |
pub struct Base { | |
ptr: *const c_int, | |
} | |
impl Base { | |
pub fn new() -> Base { | |
unsafe { | |
let ptr = event_init(); | |
assert!(!ptr.is_null()); | |
return Base { | |
ptr: ptr, | |
} | |
} | |
} | |
pub fn dispatch(&self) -> i32 { | |
unsafe { | |
return event_base_dispatch(self.ptr) as i32 | |
} | |
} | |
extern "C" | |
fn c_watch_fd_callback(ev:*const c_int, type_:c_short, cb: watch_fd_callback_t) { | |
cb(ev, type_) | |
} | |
pub fn watch_fd(&self, fd: RawFd, cb: watch_fd_callback_t) { | |
unsafe { | |
let EV_READ:c_short = 0x02; | |
let ev = event_new(self.ptr, fd, EV_READ, Base::c_watch_fd_callback, cb); | |
assert!(!ev.is_null()); | |
let res = event_add(ev, null()); | |
assert!(res == 0); | |
} | |
} | |
} | |
impl Drop for Base { | |
fn drop(&mut self) { | |
unsafe { | |
event_base_free(self.ptr) | |
} | |
} | |
} | |
type watch_fd_callback_t = fn(*const c_int, c_short); | |
type c_watch_fd_callback_t = extern fn(*const c_int, c_short, watch_fd_callback_t); | |
#[link(name="event")] | |
extern { | |
fn event_init() -> *const c_int; | |
fn event_base_dispatch(ptr: *const c_int) -> c_int; | |
fn event_base_loop(ptr: *const c_int, flags: c_int) -> c_int; | |
fn event_base_free(ptr: *const c_int); | |
fn event_new(base: *const c_int, fd: RawFd, events: c_short, cb: c_watch_fd_callback_t, args: watch_fd_callback_t) -> *const c_int; | |
fn event_add(ev: *const c_int, timeout: *const c_int) -> c_int; | |
} | |
} | |
fn printme(ev: *const c_int, flags: i16) { | |
println!("hello"); | |
} | |
extern { | |
fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; | |
} | |
fn main() { | |
use linux::socketpair; | |
use libc::consts::os::bsd44::{AF_UNIX, SOCK_DGRAM}; | |
let AF_UNSPEC = 0 as i32; | |
let domain = AF_UNIX as i32; | |
let type_ = SOCK_DGRAM as i32; | |
let protocol = AF_UNSPEC as i32; | |
let (mut fd1, fd2) = socketpair(domain, type_, protocol).ok().expect("socketpair failed!"); | |
println!("{}, {}", fd1, fd2); | |
let t = thread::spawn(move || { | |
let ev = libevent::Base::new(); | |
ev.watch_fd(fd2, printme); | |
println!("waiting..."); | |
ev.dispatch(); | |
println!("waiting done"); | |
}); | |
let buf:[u8;1] = [0]; | |
let res = unsafe { | |
send(fd1, buf.as_ptr() as *const c_void, buf.len() as size_t, 0) | |
}; | |
assert_eq!(res, buf.len() as ssize_t); | |
println!("wrote!"); | |
t.join(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment