diff --git a/kernel/bootstrap/compiled_method.rb b/kernel/bootstrap/compiled_method.rb
index 7fc1ac7..05e7d32 100644
--- a/kernel/bootstrap/compiled_method.rb
+++ b/kernel/bootstrap/compiled_method.rb
@@ -1,4 +1,14 @@
 class CompiledMethod
+  def self.load_from_file(path, version)
+    Ruby.primitive :load_file
+    raise PrimitiveFailure, "primitive failed"
+  end
+
+  def activate_as_script
+    Ruby.primitive :activate_as_script
+    raise PrimitiveFailure, "primitive failed"
+  end
+
   def compile
     Ruby.primitive :iseq_compile
     raise PrimitiveFailure, "primitive failed"
diff --git a/kernel/bootstrap/io.rb b/kernel/bootstrap/io.rb
index e3e282f..9ae1bf3 100644
--- a/kernel/bootstrap/io.rb
+++ b/kernel/bootstrap/io.rb
@@ -4,6 +4,11 @@ class IO
     raise PrimitiveFailure, "primitive failed"
   end

+  def self.create_pipe(lhs, rhs)
+    Ruby.primitive :create_pipe
+    raise PrimitiveFailure, "primitive failed"
+  end
+
   def write(str)
     Ruby.primitive :io_write
     raise PrimitiveFailure, "IO#write failed. Might not have passed a string."
@@ -31,4 +36,19 @@ class IO
   def ttyname
     prim_operation(1)
   end
+
+  def reopen(other)
+    Ruby.primitive :io_reopen
+    raise ArgumentError, "only accepts an IO object"
+  end
+
+  def io_close
+    Ruby.primitive :io_close
+    raise PrimitiveFailure, "primitive failed"
+  end
+
+  def close
+    Ruby.primitive :io_close_ng
+    raise PrimitiveFailure, "IO#close primitive failed"
+  end
 end
diff --git a/kernel/bootstrap/object.rb b/kernel/bootstrap/object.rb
index 75aeb87..980bca7 100644
--- a/kernel/bootstrap/object.rb
+++ b/kernel/bootstrap/object.rb
@@ -47,4 +47,8 @@ class Object
     raise PrimitiveFailure, "primitive failed"
   end

+  def become!(obj)
+    Ruby.primitive :object_become
+    raise PrimitiveFailure, "primitive failed"
+  end
 end
diff --git a/kernel/bootstrap/primitives.rb b/kernel/bootstrap/primitives.rb
deleted file mode 100644
index 95c22e2..0000000
--- a/kernel/bootstrap/primitives.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# All primitives not else where in the bootstrap must be here.
-
-class Object
-  def become!(obj)
-    Ruby.primitive :object_become
-    raise PrimitiveFailure, "primitive failed"
-  end
-end
-
-class IO
-  def self.create_pipe(lhs, rhs)
-    Ruby.primitive :create_pipe
-    raise PrimitiveFailure, "primitive failed"
-  end
-  
-  def reopen(other)
-    Ruby.primitive :io_reopen
-    raise ArgumentError, "only accepts an IO object"
-  end
-  
-  def io_close
-    Ruby.primitive :io_close
-    raise PrimitiveFailure, "primitive failed"
-  end
-end
-
-class CompiledMethod
-  def self.load_from_file(path, version)
-    Ruby.primitive :load_file
-    raise PrimitiveFailure, "primitive failed"
-  end
-
-  def activate_as_script
-    Ruby.primitive :activate_as_script
-    raise PrimitiveFailure, "primitive failed"
-  end
-end
diff --git a/kernel/core/io.rb b/kernel/core/io.rb
index b521bfa..c72e2e5 100644
--- a/kernel/core/io.rb
+++ b/kernel/core/io.rb
@@ -529,13 +529,6 @@ class IO
     return 0
   end

-  def close()
-    raise IOError, "Instance of IO already closed" if closed?
-
-    io_close or raise SystemCallError, "Invalid file descriptor"
-    nil
-  end
-
   def descriptor
     @descriptor
   end
diff --git a/shotgun/lib/primitives.rb b/shotgun/lib/primitives.rb
index a9492b7..a6abb18 100644
--- a/shotgun/lib/primitives.rb
+++ b/shotgun/lib/primitives.rb
@@ -4538,6 +4538,28 @@ class ShotgunPrimitives
     }
     CODE
   end
+
+  defprim :io_close_ng
+  def io_close_ng
+    <<-CODE
+    ARITY(0);
+    native_int j;
+
+    GUARD(IO_P(msg->recv));
+
+    j = io_to_fd(msg->recv);
+
+    if(j == -1) {
+      RAISE("IOError", "instance of IO already closed");
+    } else if(close(j)) {
+      RAISE_FROM_ERRNO("Unable to close IO object");
+    } else {
+      cpu_event_clear(state, j);
+      io_set_descriptor(msg->recv, I2N(-1));
+      RET(Qnil);
+    }
+    CODE
+  end
 end

 prim = ShotgunPrimitives.new