diff --git a/MissingPy.cabal b/MissingPy.cabal
--- a/MissingPy.cabal
+++ b/MissingPy.cabal
@@ -1,5 +1,5 @@
 Name: MissingPy
-Version: 0.10.5
+Version: 0.10.6
 License: MIT
 Maintainer: Matt Brown <matt@softmechanics.net>
 Author: John Goerzen
diff --git a/Python/Exceptions/ExcTypes.hsc b/Python/Exceptions/ExcTypes.hsc
--- a/Python/Exceptions/ExcTypes.hsc
+++ b/Python/Exceptions/ExcTypes.hsc
@@ -88,7 +88,7 @@
 import Python.Objects
 import System.IO.Unsafe
 import Python.Utils
-import Foreign
+import Foreign hiding (unsafePerformIO)
 exctypes_internal_e :: IO (Ptr CPyObject) -> IO PyObject
 exctypes_internal_e f = do p <- f
                            fp <- newForeignPtr_ p
diff --git a/Python/Interpreter.hs b/Python/Interpreter.hs
--- a/Python/Interpreter.hs
+++ b/Python/Interpreter.hs
@@ -100,24 +100,64 @@
                     )
 
 import Foreign.C (withCString)
-import Control.Exception (finally)
+import Control.Exception (handle, finally, throwTo, SomeException)
+import Control.Concurrent (rtsSupportsBoundThreads, forkOS, myThreadId)
+import Control.Concurrent.MVar
+import System.IO.Unsafe
 
 {- | Initialize the Python interpreter environment.
 
 MUST BE DONE BEFORE DOING ANYTHING ELSE! -}
-py_initialize :: IO ()
-py_initialize = do cpy_initialize
-                   pyImport "traceback"
+py_initialize =  
+  if rtsSupportsBoundThreads
+     then py_initializeThreaded
+     else py_initialize'
 
+py_initialize' :: IO ()
+py_initialize' = do cpy_initialize
+                    pyImport "traceback"
+
+{- Python use Thread Local Storage, so all calls must be made through a 
+ - single OS thread.
+ -}
+
 py_initializeThreaded :: IO ()
-py_initializeThreaded = do cpy_InitThreads
-                           py_initialize
-                           
-#ifndef PYTHON_PRE_2_3
-withGIL :: IO a -> IO a                           
-withGIL act = do st <- cpy_GILEnsure
-                 finally act
-                   (cpy_GILRelease st)
+py_initializeThreaded = do 
+  forkOS $ do 
+    cpy_InitThreads
+    py_initialize'
+    pyPoll
+  return ()
+                             
+pyQ :: MVar (IO ())
+pyQ = unsafePerformIO newEmptyMVar
+
+{- Poll pyQ for python actions, and execute them -}
+pyPoll = do
+  a <- takeMVar pyQ
+  withGIL' a >> pyPoll
+
+{- Pass python actions to dedicated python thread for execution. -} 
+withGIL :: IO a -> IO a
+withGIL = 
+  if rtsSupportsBoundThreads
+     then withGILThreaded
+     else withGIL'
+
+withGILThreaded :: IO a -> IO a
+withGILThreaded act = do
+  tid <- myThreadId
+  r <- newEmptyMVar
+  putMVar pyQ $ handle (\e -> throwTo tid (e::SomeException)) $ putMVar r =<< act
+  takeMVar r
+
+withGIL' :: IO a -> IO a                           
+#ifdef PYTHON_PRE_2_3
+withGIL' a = a
+#else
+withGIL' act = do st <- cpy_GILEnsure
+                  finally act
+                    (cpy_GILRelease st)
 #endif                 
 
 pyRun_SimpleString :: String -> IO ()
