summaryrefslogtreecommitdiff
path: root/meap/meap-code/ch10
diff options
context:
space:
mode:
Diffstat (limited to 'meap/meap-code/ch10')
-rw-r--r--meap/meap-code/ch10/Vagrantfile29
-rw-r--r--meap/meap-code/ch10/ch10-basic-handler/Cargo.toml9
-rw-r--r--meap/meap-code/ch10/ch10-basic-handler/Dockerfile36
-rw-r--r--meap/meap-code/ch10/ch10-basic-handler/Makefile2
-rw-r--r--meap/meap-code/ch10/ch10-basic-handler/src/main.rs58
-rw-r--r--meap/meap-code/ch10/ch10-callstack/Cargo.toml6
-rw-r--r--meap/meap-code/ch10/ch10-callstack/src/main.rs21
-rw-r--r--meap/meap-code/ch10/ch10-handle/Cargo.toml7
-rw-r--r--meap/meap-code/ch10/ch10-handle/src/main.rs48
-rw-r--r--meap/meap-code/ch10/ch10-handler/Cargo.toml7
-rw-r--r--meap/meap-code/ch10/ch10-handler/src/main.rs58
-rw-r--r--meap/meap-code/ch10/ch10-ignore/Cargo.toml7
-rw-r--r--meap/meap-code/ch10/ch10-ignore/src/main.rs18
-rw-r--r--meap/meap-code/ch10/ch10-sixty/Cargo.toml6
-rw-r--r--meap/meap-code/ch10/ch10-sixty/src/main.rs15
-rw-r--r--meap/meap-code/ch10/ch10-sjlj/Cargo.toml7
-rw-r--r--meap/meap-code/ch10/ch10-sjlj/Dockerfile37
-rw-r--r--meap/meap-code/ch10/ch10-sjlj/Makefile2
-rw-r--r--meap/meap-code/ch10/ch10-sjlj/src/main.rs105
19 files changed, 478 insertions, 0 deletions
diff --git a/meap/meap-code/ch10/Vagrantfile b/meap/meap-code/ch10/Vagrantfile
new file mode 100644
index 0000000..b306dd1
--- /dev/null
+++ b/meap/meap-code/ch10/Vagrantfile
@@ -0,0 +1,29 @@
+VAGRANTFILE_VERSION = "2"
+
+$provision_external = <<SCRIPT
+sudo apt-get -qq update
+sudo apt-get install -q -y curl
+
+curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
+SCRIPT
+
+# $provision_internal = <<SCRIPT
+# cd ~
+# mkdir code
+# sudo mount -t vboxsf code ./code
+# SCRIPT
+
+
+Vagrant.configure(VAGRANTFILE_VERSION) do |config|
+
+ config.vm.provider "virtualbox" do |v|
+ v.name = "rust_in_action"
+ v.linked_clone = true
+ end
+
+ config.vm.box = "bento/ubuntu-17.04-i386"
+ config.vm.synced_folder ".", "/ch10/"
+ config.vm.post_up_message = "Hope that you're enjoying Rust in Action!\n-TS McNamara"
+ config.vm.provision "shell", inline: $provision_external
+ #config.vm.provision "shell", inline: $provision_internal
+end \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-basic-handler/Cargo.toml b/meap/meap-code/ch10/ch10-basic-handler/Cargo.toml
new file mode 100644
index 0000000..7cc2735
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-basic-handler/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "basic-handler"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+
+[target.'cfg(not(windows))'.dependencies]
+libc = "0.2" \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-basic-handler/Dockerfile b/meap/meap-code/ch10/ch10-basic-handler/Dockerfile
new file mode 100644
index 0000000..cc17065
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-basic-handler/Dockerfile
@@ -0,0 +1,36 @@
+# strategy sourced from:
+
+# https://www.fpcomplete.com/blog/2018/07/deploying-rust-with-docker-and-kubernetes
+# http://whitfin.io/speeding-up-rust-docker-builds/
+
+# This image will build all dependencies before you
+# introducing the project's source code, which means
+# they'll be cached most of the time.
+
+FROM rust:latest as intermediate
+RUN rustup target add x86_64-unknown-linux-musl
+
+ENV PATH $PATH:/root/.cargo/bin
+ENV PKG_CONFIG_ALLOW_CROSS=1
+
+# fetch dependencies using a minimal project,
+# enabling the docker image to be cached with dependencies installed
+RUN USER=root cargo new --bin project
+WORKDIR /project
+
+COPY ./Cargo.lock ./Cargo.lock
+COPY ./Cargo.toml ./Cargo.toml
+
+#RUN cargo -v build --target x86_64-unknown-linux-musl
+
+# build actual project
+#RUN rm src/*.rs
+COPY ./src ./src
+RUN cargo -v check
+RUN cargo -v build --target x86_64-unknown-linux-musl
+RUN ls -R /project/target
+
+FROM alpine
+COPY --from=intermediate /project/target/x86_64-unknown-linux-musl/debug/basic-handler /
+
+CMD /basic-handler
diff --git a/meap/meap-code/ch10/ch10-basic-handler/Makefile b/meap/meap-code/ch10/ch10-basic-handler/Makefile
new file mode 100644
index 0000000..9d1a25f
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-basic-handler/Makefile
@@ -0,0 +1,2 @@
+container:
+ docker build -t ria-ch10-simple-handler . \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-basic-handler/src/main.rs b/meap/meap-code/ch10/ch10-basic-handler/src/main.rs
new file mode 100644
index 0000000..a7ecb33
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-basic-handler/src/main.rs
@@ -0,0 +1,58 @@
+#![cfg(not(windows))] // <1>
+
+extern crate libc;
+
+use std::mem;
+use std::time;
+use std::thread::{sleep};
+use libc::{SIGTERM, SIGALRM, SIGHUP, SIGQUIT};
+
+static mut SHUT_DOWN: bool = false;
+
+fn register_signal_handler() {
+ let fn_ptr: fn(i32) -> () = handle_signals; // <2>
+
+ unsafe {
+ let fn_ptr_as_usize: usize = mem::transmute(fn_ptr); // <3>
+ libc::signal(SIGTERM, fn_ptr_as_usize); // <4>
+ }
+}
+
+#[allow(dead_code)] // <5>
+fn handle_signals(sig: i32) {
+ register_signal_handler();
+
+ unsafe { // <6>
+ SHUT_DOWN = match sig { // <7>
+ SIGHUP => false, // <7>
+ SIGALRM => false, // <7>
+ SIGTERM => true, // <7>
+ SIGQUIT => true, // <7>
+ _ => false, // <7>
+ };
+ }
+}
+
+fn main() {
+
+ register_signal_handler();
+ let delay = time::Duration::from_secs(1);
+
+ for i in 1_usize.. { // <7>
+ unsafe { // <7>
+ if SHUT_DOWN {
+ println!(); // only print a newline character
+ return;
+ }
+ }
+
+ sleep(delay);
+ print!("{} ", i);
+
+ if i > 10 {
+ unsafe {
+ libc::raise(SIGTERM);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-callstack/Cargo.toml b/meap/meap-code/ch10/ch10-callstack/Cargo.toml
new file mode 100644
index 0000000..af00325
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-callstack/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "ch10-callstack"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch10/ch10-callstack/src/main.rs b/meap/meap-code/ch10/ch10-callstack/src/main.rs
new file mode 100644
index 0000000..cbb56e3
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-callstack/src/main.rs
@@ -0,0 +1,21 @@
+fn print_depth(depth:usize) {
+ for _ in 0..depth {
+ print!("#");
+ }
+ println!("");
+}
+
+fn dive(depth: usize, max_depth: usize) {
+ print_depth(depth);
+ if depth >= max_depth {
+ return;
+
+ } else {
+ dive(depth+1, max_depth);
+ }
+ print_depth(depth);
+}
+
+fn main() {
+ dive(0, 5);
+} \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-handle/Cargo.toml b/meap/meap-code/ch10/ch10-handle/Cargo.toml
new file mode 100644
index 0000000..95fa6c0
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-handle/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "ch10-handle"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+libc = "0.2" \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-handle/src/main.rs b/meap/meap-code/ch10/ch10-handle/src/main.rs
new file mode 100644
index 0000000..d40e329
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-handle/src/main.rs
@@ -0,0 +1,48 @@
+extern crate libc; // 0.2.42
+
+use std::time::{Duration};
+use std::thread::{sleep};
+use libc::{signal,raise};
+use libc::{SIG_DFL, SIG_IGN, SIGTERM, SIGHUP};
+
+type handler_ptr = extern "C" fn(i32) -> ();
+
+static mut ABORT: bool = false;
+
+#[inline(never)]
+extern "C" fn handle_signals(sig: i32) { // rustc will warn that that this code is never run
+ let handle_signals_ptr: handler_ptr = handle_signals;
+ unsafe { // set the signal handler again, to prevent it resetting to SIG_DFL
+ signal(SIGTERM, std::mem::transmute(handle_signals_ptr));
+ }
+
+ let should_abort = match sig {
+ SIGTERM => true,
+ SIGHUP => false,
+ _ => false,
+ };
+
+ unsafe { // make a quick update here, and defer the real work to somewhere else
+ ABORT = should_abort;
+ }
+}
+
+fn main() {
+ let delay = Duration::from_secs(1);
+
+ // "main loop"
+ for i in 1..=60 {
+ unsafe { // at every step, check to see if a signal has been sent
+ if ABORT {
+ break;
+ }
+ }
+
+ sleep(delay);
+ println!(". {}", i);
+
+ if i > 2 {
+ unsafe { raise(SIGTERM); }
+ }
+ }
+} \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-handler/Cargo.toml b/meap/meap-code/ch10/ch10-handler/Cargo.toml
new file mode 100644
index 0000000..7c8ed67
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-handler/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "ch10-handler"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+libc = "0.2"
diff --git a/meap/meap-code/ch10/ch10-handler/src/main.rs b/meap/meap-code/ch10/ch10-handler/src/main.rs
new file mode 100644
index 0000000..088c9e6
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-handler/src/main.rs
@@ -0,0 +1,58 @@
+#![cfg(not(windows))]
+
+extern crate libc;
+
+use std::mem;
+use std::time;
+use std::thread::{sleep};
+use libc::{SIGTERM, SIGALRM, SIGHUP, SIGQUIT};
+
+static mut SHUT_DOWN: bool = false;
+
+#[inline]
+fn register_signal_handler() {
+ let fn_ptr: fn(i32) -> () = handle_signals; // <1> hardcoding for simplicity
+
+ unsafe {
+ let fn_ptr_as_usize: usize = mem::transmute(fn_ptr); // <2>
+ libc::signal(SIGTERM, fn_ptr_as_usize); // <3>
+ }
+}
+
+#[allow(dead_code)] // <4>
+fn handle_signals(sig: i32) {
+ register_signal_handler();
+
+ unsafe { // <4>
+ SHUT_DOWN = match sig { // <5>
+ SIGALRM => false, // <5>
+ SIGHUP => false, // <5>
+ SIGTERM => true, // <5>
+ SIGQUIT => true, // <5>
+ _ => false, // <5>
+ };
+ }
+}
+
+fn main() {
+ register_signal_handler();
+ let delay = time::Duration::from_secs(1);
+
+ for i in 1.. { // <6>
+ unsafe { // <6>
+ if SHUT_DOWN {
+ println!(); // only print a newline character
+ return;
+ }
+ }
+
+ sleep(delay);
+ print!(".");
+
+ if i > 3 {
+ unsafe {
+ libc::raise(SIGTERM);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-ignore/Cargo.toml b/meap/meap-code/ch10/ch10-ignore/Cargo.toml
new file mode 100644
index 0000000..0184c84
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-ignore/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "ch10-ignore"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+libc = "0.2" \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-ignore/src/main.rs b/meap/meap-code/ch10/ch10-ignore/src/main.rs
new file mode 100644
index 0000000..9f68362
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-ignore/src/main.rs
@@ -0,0 +1,18 @@
+extern crate libc; // 0.2.42
+
+use libc::{signal,raise};
+use libc::{SIG_DFL, SIG_IGN, SIGTERM};
+
+fn main() {
+ unsafe {
+ signal(SIGTERM, SIG_IGN);
+ raise(SIGTERM);
+ }
+ println!("ok");
+
+ unsafe {
+ signal(SIGTERM, SIG_DFL);
+ raise(SIGTERM);
+ }
+ println!("not ok");
+} \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-sixty/Cargo.toml b/meap/meap-code/ch10/ch10-sixty/Cargo.toml
new file mode 100644
index 0000000..a0ad51e
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sixty/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "ch10-sixty"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch10/ch10-sixty/src/main.rs b/meap/meap-code/ch10/ch10-sixty/src/main.rs
new file mode 100644
index 0000000..74ffa90
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sixty/src/main.rs
@@ -0,0 +1,15 @@
+use std::time;
+use std::process;
+use std::thread::sleep;
+
+fn main() {
+ let delay = time::Duration::from_secs(1);
+
+ let pid = process::id();
+ println!("{}", pid);
+
+ for i in 1..=60 {
+ sleep(delay);
+ println!(". {}", i);
+ }
+}
diff --git a/meap/meap-code/ch10/ch10-sjlj/Cargo.toml b/meap/meap-code/ch10/ch10-sjlj/Cargo.toml
new file mode 100644
index 0000000..c9eab65
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sjlj/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "ch10-sjlj"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+libc = "0.2" \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-sjlj/Dockerfile b/meap/meap-code/ch10/ch10-sjlj/Dockerfile
new file mode 100644
index 0000000..ba5e1f0
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sjlj/Dockerfile
@@ -0,0 +1,37 @@
+# build strategy sourced from:
+# - https://www.fpcomplete.com/blog/2018/07/deploying-rust-with-docker-and-kubernetes
+# - http://whitfin.io/speeding-up-rust-docker-builds/
+
+# This image will build all dependencies before you
+# introducing the project's source code, which means
+# they'll be cached most of the time.
+
+FROM rust:latest as intermediate
+RUN rustup toolchain install nightly
+RUN rustup default nightly
+RUN rustup target add x86_64-unknown-linux-musl
+
+ENV PATH $PATH:/root/.cargo/bin
+ENV PKG_CONFIG_ALLOW_CROSS=1
+
+# fetch dependencies using a minimal project,
+# enabling the docker image to be cached with dependencies installed
+RUN USER=root cargo new --bin project
+WORKDIR /project
+
+COPY ./Cargo.lock ./Cargo.lock
+COPY ./Cargo.toml ./Cargo.toml
+
+#RUN cargo -v build --target x86_64-unknown-linux-musl
+
+# build actual project
+#RUN rm src/*.rs
+COPY ./src ./src
+RUN cargo +nightly -v check
+RUN cargo +nightly -v build --target x86_64-unknown-linux-musl
+RUN ls -R /project/target
+
+FROM alpine
+COPY --from=intermediate /project/target/x86_64-unknown-linux-musl/debug/ch10-sjlj /
+
+CMD /ch10-sjlj
diff --git a/meap/meap-code/ch10/ch10-sjlj/Makefile b/meap/meap-code/ch10/ch10-sjlj/Makefile
new file mode 100644
index 0000000..d68912d
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sjlj/Makefile
@@ -0,0 +1,2 @@
+container:
+ docker build -t ria-ch10-sjlj . \ No newline at end of file
diff --git a/meap/meap-code/ch10/ch10-sjlj/src/main.rs b/meap/meap-code/ch10/ch10-sjlj/src/main.rs
new file mode 100644
index 0000000..baac669
--- /dev/null
+++ b/meap/meap-code/ch10/ch10-sjlj/src/main.rs
@@ -0,0 +1,105 @@
+#![feature(link_llvm_intrinsics)]
+#![allow(non_camel_case_types)]
+#![cfg(not(windows))]
+
+extern crate libc;
+
+use libc::{SIGUSR1, SIGALRM, SIGHUP, SIGQUIT, SIGTERM};
+use std::mem;
+
+const JMP_BUF_WIDTH: usize = mem::size_of::<usize>() * 8;
+type jmp_buf = [i8; JMP_BUF_WIDTH];
+
+static mut SHUT_DOWN: bool = false;
+static mut RETURN_HERE: jmp_buf = [0; JMP_BUF_WIDTH];
+const MOCK_SIGNAL_AT: usize = 3;
+
+extern "C" {
+ #[link_name = "llvm.setjmp"]
+ pub fn setjmp(a: *mut i8) -> i32;
+
+ #[link_name = "llvm.longjmp"]
+ pub fn longjmp(a: *mut i8, b: i32) -> ();
+}
+
+#[inline]
+fn ptr_to_jmp_buf() -> *mut i8 {
+ unsafe { &RETURN_HERE as *const i8 as *mut i8 }
+}
+
+#[inline]
+fn return_early() {
+ let franken_pointer = ptr_to_jmp_buf();
+ unsafe { longjmp(franken_pointer, 1) };
+}
+
+fn register_signal_handler() {
+ unsafe {
+ libc::signal(SIGUSR1, handle_signals as usize); // <4>
+ }
+}
+
+#[allow(dead_code)] // <5>
+fn handle_signals(sig: i32) {
+ register_signal_handler(); // Immediately re-registering the signal handler minimizes the chances of a missing a signal.
+
+ let should_shut_down = match sig {
+ SIGHUP => false, // <7>
+ SIGALRM => false, // <7>
+ SIGTERM => true, // <7>
+ SIGQUIT => true, // <7>
+ SIGUSR1 => true,
+ _ => false, // <7>
+ };
+
+ unsafe {
+ // This unsafe block is required because we are modifying a global static variable.
+ SHUT_DOWN = should_shut_down;
+ }
+
+ return_early();
+}
+
+fn print_depth(depth: usize) {
+ for _ in 0..depth {
+ print!("#");
+ }
+ println!("");
+}
+
+fn dive(depth: usize, max_depth: usize) {
+ unsafe {
+ if SHUT_DOWN == true {
+ println!("!");
+ return;
+ }
+ }
+ print_depth(depth);
+
+ if depth >= max_depth {
+ return;
+ } else if depth == MOCK_SIGNAL_AT {
+ unsafe {
+ libc::raise(SIGUSR1);
+ }
+ } else {
+ dive(depth + 1, max_depth);
+ }
+ print_depth(depth);
+}
+
+fn main() {
+ const JUMP_SET: i32 = 0;
+
+ register_signal_handler();
+
+ let return_point = ptr_to_jmp_buf();
+ let rc = unsafe { setjmp(return_point) };
+ if rc == JUMP_SET {
+ dive(0, 10);
+ } else {
+ println!("early return!");
+ }
+
+ println!("finishing!")
+}