diff --git a/Cargo.lock b/Cargo.lock
index 2351f79c045ce085adafa24e6fe0d49369a317cd..224eaaa31cdbea9180878fde3e90fa4e3b122b5d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -262,6 +262,7 @@ dependencies = [
  "platform 0.1.0",
  "resource 0.1.0",
  "semaphore 0.1.0",
+ "signal 0.1.0",
  "stat 0.1.0",
  "stdio 0.1.0",
  "stdlib 0.1.0",
@@ -342,6 +343,14 @@ dependencies = [
  "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "signal"
+version = "0.1.0"
+dependencies = [
+ "cbindgen 0.5.2",
+ "platform 0.1.0",
+]
+
 [[package]]
 name = "standalone-quote"
 version = "0.5.0"
diff --git a/Cargo.toml b/Cargo.toml
index 85785975e82bc6c7af1926a8c3d6d702667d5b29..ffd5eea4ec7497341ebdb38d40dc67f919b115d4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,6 +22,7 @@ mman = { path = "src/mman" }
 platform = { path = "src/platform" }
 resource = { path = "src/resource" }
 semaphore = { path = "src/semaphore" }
+signal = { path = "src/signal" }
 stat = { path = "src/stat" }
 stdio = { path = "src/stdio" }
 stdlib = { path = "src/stdlib" }
diff --git a/include/bits/signal.h b/include/bits/signal.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a6a8345d28293871d9ac917575b70545a6659e7
--- /dev/null
+++ b/include/bits/signal.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_SIGNAL_H
+#define _BITS_SIGNAL_H
+
+typedef struct sigaction {
+  void (*sa_handler)(uintptr_t);
+  sigset_t sa_mask;
+  uintptr_t sa_flags;
+};
+
+#endif
diff --git a/include/bits/timespec.h b/include/bits/timespec.h
index 52d696fc3129c3a14a9f2dce1c351e0c5aea567f..5f36eaa8cc3bc1c28db802742fa14398411aa169 100644
--- a/include/bits/timespec.h
+++ b/include/bits/timespec.h
@@ -1,4 +1,9 @@
+#ifndef _BITS_TIMESPEC_H
+#define _BITS_TIMESPEC_H
+
 typedef struct {
     time_t tv_sec;
     long tv_nsec;
 } timespec;
+
+#endif
diff --git a/src/fcntl/cbindgen.toml b/src/fcntl/cbindgen.toml
index 19d473cd4a9d5f82dddcd2ecfcddb27e44709664..d49feaa87a14439d500104dde368bf9341973200 100644
--- a/src/fcntl/cbindgen.toml
+++ b/src/fcntl/cbindgen.toml
@@ -4,8 +4,8 @@ trailer = "#include <bits/fcntl.h>"
 language = "C"
 
 [defines]
-"target_os = linux" = "__linux__"
-"target_os = redox" = "__redox__"
+"target_os=linux" = "__linux__"
+"target_os=redox" = "__redox__"
 
 [enum]
 prefix_with_name = true
diff --git a/src/signal/Cargo.toml b/src/signal/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..b1847d0801dd0c8bcb7a61d068e26e1a26e82c83
--- /dev/null
+++ b/src/signal/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "signal"
+version = "0.1.0"
+authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
+build = "build.rs"
+
+[build-dependencies]
+cbindgen = { path = "../../cbindgen" }
+
+[dependencies]
+platform = { path = "../platform" }
diff --git a/src/signal/build.rs b/src/signal/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..011ccd1588c78697e4e700e9bbbd692ffbbd0f94
--- /dev/null
+++ b/src/signal/build.rs
@@ -0,0 +1,11 @@
+extern crate cbindgen;
+
+use std::{env, fs};
+
+fn main() {
+    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
+    fs::create_dir_all("../../target/include").expect("failed to create include directory");
+    cbindgen::generate(crate_dir)
+        .expect("failed to generate bindings")
+        .write_to_file("../../target/include/signal.h");
+}
diff --git a/src/signal/cbindgen.toml b/src/signal/cbindgen.toml
new file mode 100644
index 0000000000000000000000000000000000000000..87d334c40d12e68bdceec1285de9963da56b69b9
--- /dev/null
+++ b/src/signal/cbindgen.toml
@@ -0,0 +1,11 @@
+sys_includes = ["sys/types.h"]
+include_guard = "_SIGNAL_H"
+trailer = "#include <bits/signal.h>"
+language = "C"
+
+[defines]
+"target_os=linux" = "__linux__"
+"target_os=redox" = "__redox__"
+
+[enum]
+prefix_with_name = true
diff --git a/src/signal/src/lib.rs b/src/signal/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..80ec786e331653ceb351e324f3a9a3e49f635df6
--- /dev/null
+++ b/src/signal/src/lib.rs
@@ -0,0 +1,124 @@
+//! signal implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html
+
+#![no_std]
+
+extern crate platform;
+
+#[cfg(target_os = "linux")]
+#[path = "linux.rs"]
+pub mod sys;
+
+#[cfg(target_os = "redox")]
+#[path = "redox.rs"]
+pub mod sys;
+
+pub use sys::*;
+
+use platform::types::*;
+
+#[repr(C)]
+pub struct sigaction {
+    pub sa_handler: extern "C" fn(usize),
+    pub sa_mask: sigset_t,
+    pub sa_flags: usize,
+}
+
+#[no_mangle]
+pub extern "C" fn kill(pid: pid_t, sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn raise(sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigaction(sig: c_int, act: *const sigaction, oact: *const sigaction) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigaddset(set: *mut sigset_t, signo: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigdelset(set: *mut sigset_t, signo: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigemptyset(set: *mut sigset_t) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigfillset(set: *mut sigset_t) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sighold(sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigignore(sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigismember(set: *const sigset_t, signo: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn signal(sig: c_int, func: fn(c_int)) -> fn(c_int) {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigpause(sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigpending(set: *mut sigset_t) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigrelse(sig: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigset(sig: c_int, func: fn(c_int)) -> fn(c_int) {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigsuspend(sigmask: *const sigset_t) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int {
+    unimplemented!();
+}
diff --git a/src/signal/src/linux.rs b/src/signal/src/linux.rs
new file mode 100644
index 0000000000000000000000000000000000000000..63eff1c144d5888806f3b1ddafab65d619fb8b30
--- /dev/null
+++ b/src/signal/src/linux.rs
@@ -0,0 +1,48 @@
+#[repr(C)]
+pub struct sigset_t {
+    pub bits: [u64; 16],
+}
+
+pub const SIGHUP: usize = 1;
+pub const SIGINT: usize = 2;
+pub const SIGQUIT: usize = 3;
+pub const SIGILL: usize = 4;
+pub const SIGTRAP: usize = 5;
+pub const SIGABRT: usize = 6;
+pub const SIGIOT: usize = SIGABRT;
+pub const SIGBUS: usize = 7;
+pub const SIGFPE: usize = 8;
+pub const SIGKILL: usize = 9;
+pub const SIGUSR1: usize = 10;
+pub const SIGSEGV: usize = 11;
+pub const SIGUSR2: usize = 12;
+pub const SIGPIPE: usize = 13;
+pub const SIGALRM: usize = 14;
+pub const SIGTERM: usize = 15;
+pub const SIGSTKFLT: usize = 16;
+pub const SIGCHLD: usize = 17;
+pub const SIGCONT: usize = 18;
+pub const SIGSTOP: usize = 19;
+pub const SIGTSTP: usize = 20;
+pub const SIGTTIN: usize = 21;
+pub const SIGTTOU: usize = 22;
+pub const SIGURG: usize = 23;
+pub const SIGXCPU: usize = 24;
+pub const SIGXFSZ: usize = 25;
+pub const SIGVTALRM: usize = 26;
+pub const SIGPROF: usize = 27;
+pub const SIGWINCH: usize = 28;
+pub const SIGIO: usize = 29;
+pub const SIGPOLL: usize = 29;
+pub const SIGPWR: usize = 30;
+pub const SIGSYS: usize = 31;
+pub const SIGUNUSED: usize = SIGSYS;
+
+pub const SA_NOCLDSTOP: usize = 1;
+pub const SA_NOCLDWAIT: usize = 2;
+pub const SA_SIGINFO: usize = 4;
+pub const SA_ONSTACK: usize = 0x08000000;
+pub const SA_RESTART: usize = 0x10000000;
+pub const SA_NODEFER: usize = 0x40000000;
+pub const SA_RESETHAND: usize = 0x80000000;
+pub const SA_RESTORER: usize = 0x04000000;
diff --git a/src/signal/src/redox.rs b/src/signal/src/redox.rs
new file mode 100644
index 0000000000000000000000000000000000000000..54cb42adc53d3fc9f88d0720594c3fdd07a042df
--- /dev/null
+++ b/src/signal/src/redox.rs
@@ -0,0 +1,44 @@
+#[repr(C)]
+pub struct sigset_t {
+    pub bits: [u64; 2],
+}
+
+pub const SIGHUP: usize = 1;
+pub const SIGINT: usize = 2;
+pub const SIGQUIT: usize = 3;
+pub const SIGILL: usize = 4;
+pub const SIGTRAP: usize = 5;
+pub const SIGBUS: usize = 7;
+pub const SIGFPE: usize = 8;
+pub const SIGKILL: usize = 9;
+pub const SIGUSR1: usize = 10;
+pub const SIGSEGV: usize = 11;
+pub const SIGUSR2: usize = 12;
+pub const SIGPIPE: usize = 13;
+pub const SIGALRM: usize = 14;
+pub const SIGTERM: usize = 15;
+pub const SIGSTKFLT: usize = 16;
+pub const SIGCHLD: usize = 17;
+pub const SIGCONT: usize = 18;
+pub const SIGSTOP: usize = 19;
+pub const SIGTSTP: usize = 20;
+pub const SIGTTIN: usize = 21;
+pub const SIGTTOU: usize = 22;
+pub const SIGURG: usize = 23;
+pub const SIGXCPU: usize = 24;
+pub const SIGXFSZ: usize = 25;
+pub const SIGVTALRM: usize = 26;
+pub const SIGPROF: usize = 27;
+pub const SIGWINCH: usize = 28;
+pub const SIGIO: usize = 29;
+pub const SIGPWR: usize = 30;
+pub const SIGSYS: usize = 31;
+
+pub const SA_NOCLDSTOP: usize = 0x00000001;
+pub const SA_NOCLDWAIT: usize = 0x00000002;
+pub const SA_SIGINFO: usize = 0x00000004;
+pub const SA_RESTORER: usize = 0x04000000;
+pub const SA_ONSTACK: usize = 0x08000000;
+pub const SA_RESTART: usize = 0x10000000;
+pub const SA_NODEFER: usize = 0x40000000;
+pub const SA_RESETHAND: usize = 0x80000000;