Skip to content

Instantly share code, notes, and snippets.

@manuels
Created April 22, 2015 09:26
Show Gist options
  • Save manuels/8c264818252cabe3081c to your computer and use it in GitHub Desktop.
Save manuels/8c264818252cabe3081c to your computer and use it in GitHub Desktop.
not-crashing-anymore.rs
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