diff --git a/hzk.cabal b/hzk.cabal
--- a/hzk.cabal
+++ b/hzk.cabal
@@ -1,7 +1,7 @@
 name:          hzk
 author:        DiegoSouza <dsouza@c0d3.xxx>
 license:       BSD3
-version:       1.0.1
+version:       2.0.0
 category:      Database
 homepage:      http://github.com/dgvncsz0f/hzk
 synopsis:      Haskell client library for Apache Zookeeper
diff --git a/src/Database/Zookeeper.hs b/src/Database/Zookeeper.hs
--- a/src/Database/Zookeeper.hs
+++ b/src/Database/Zookeeper.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE Safe #-}
+{-# LANGUAGE Safe          #-}
+{-# LANGUAGE TupleSections #-}
 
 -- This file is part of zhk
 --
@@ -174,7 +175,7 @@
 setDebugLevel :: ZLogLevel -> IO ()
 setDebugLevel = c_zooSetDebugLevel . fromLogLevel
 
--- | Creates a znode (asynchornous)
+-- | Creates a znode
 create :: Zookeeper
        -- ^ Zookeeper handle
        -> String
@@ -186,17 +187,18 @@
        -- ^ The initial ACL of the node. The ACL must not be empty
        -> [CreateFlag]
        -- ^ Optional, may be empty
-       -> (Either ZKError String -> IO ())
-       -- ^ The callback function
-       -> IO ()
-create (Zookeeper zh) path mvalue acls flags callback =
+       -> IO (Either ZKError String)
+create (Zookeeper zh) path mvalue acls flags =
   withCString path $ \pathPtr ->
     maybeUseAsCStringLen mvalue $ \(valuePtr, valueLen) ->
-      withAclList acls $ \aclPtr -> do
-        cStrFn <- wrapStringCompletion callback
-        rc     <- c_zooACreate zh pathPtr valuePtr (fromIntegral valueLen) aclPtr (fromCreateFlags flags) cStrFn nullPtr
-        unless (isZOK rc) (callback $ Left (toZKError rc))
+      withAclList acls $ \aclPtr ->
+        allocaBytes pathlen $ \newPathPtr -> do
+          rc <- c_zooCreate zh pathPtr valuePtr (fromIntegral valueLen) aclPtr (fromCreateFlags flags) newPathPtr (fromIntegral pathlen)
+          if (isZOK rc)
+            then fmap Right (peekCString newPathPtr)
+            else return (Left $ toZKError rc)
     where
+      pathlen = length path + 11
       maybeUseAsCStringLen Nothing f  = f (nullPtr, -1)
       maybeUseAsCStringLen (Just s) f = B.useAsCStringLen s f
 
@@ -232,7 +234,7 @@
       cWatcher <- wrapWatcher mwatcher
       tryZ (c_zooWExists zh pathPtr cWatcher nullPtr statPtr) (toStat statPtr)
 
--- | Lists the children of a znode (asynchronous)
+-- | Lists the children of a znode
 getChildren :: Zookeeper
             -- ^ Zookeeper handle
             -> String
@@ -241,15 +243,15 @@
             -> Maybe Watcher
             -- ^ The watch to be set at the server to notify the user
             -- if the node changes
-            -> (Either ZKError [String] -> IO ())
-            -- ^ The callback function
-            -> IO ()
-getChildren (Zookeeper zh) path mwatcher callback =
-  withCString path (\pathPtr -> do
-    cWatcher <- wrapWatcher mwatcher
-    cStrFn   <- wrapStringsCompletion callback
-    rc       <- c_zooAWGetChildren zh pathPtr cWatcher nullPtr cStrFn nullPtr
-    unless (isZOK rc) (callback $ Left (toZKError rc)))
+            -> IO (Either ZKError [String])
+getChildren (Zookeeper zh) path mwatcher =
+  withCString path $ \pathPtr ->
+    allocaStrVec $ \strVecPtr -> do
+      cWatcher <- wrapWatcher mwatcher
+      rc       <- c_zooWGetChildren zh pathPtr cWatcher nullPtr strVecPtr
+      if (isZOK rc)
+        then fmap Right $ toStringList strVecPtr
+        else return (Left $ toZKError rc)
 
 -- | Gets the data associated with a znode (asynchronous)
 get :: Zookeeper
@@ -260,15 +262,22 @@
     -> Maybe Watcher
     -- ^ When provided, a watch will be set at the server to notify
     -- the client if the node changes
-    -> (Either ZKError (Maybe B.ByteString, Stat) -> IO ())
-    -- ^ The callback function
-    -> IO ()
-get (Zookeeper zh) path mwatcher callback =
-  withCString path $ \pathPtr -> do
-    cWatcher <- wrapWatcher mwatcher
-    cDataFn  <- wrapDataCompletion callback
-    rc       <- c_zooAWGet zh pathPtr cWatcher nullPtr cDataFn nullPtr
-    unless (isZOK rc) (callback $ Left (toZKError rc))
+    -> IO (Either ZKError (Maybe B.ByteString, Stat))
+get (Zookeeper zh) path mwatcher =
+  withCString path $ \pathPtr ->
+    allocaBytes buffSize $ \dataPtr ->
+      allocaStat $ \statPtr ->
+        alloca $ \buffSizePtr -> do
+          poke buffSizePtr (fromIntegral buffSize)
+          cWatcher <- wrapWatcher mwatcher
+          rc       <- c_zooWGet zh pathPtr cWatcher nullPtr dataPtr buffSizePtr statPtr
+          dataSz   <- peek buffSizePtr
+          case (isZOK rc, fromIntegral dataSz) of
+            (True, -1) -> return . Right =<< fmap (Nothing ,) (toStat statPtr)
+            (True, sz) -> return . Right =<< liftM2 (,) (fmap Just $ B.packCStringLen (dataPtr, sz)) (toStat statPtr)
+            (False, _) -> return (Left $ toZKError rc)
+    where
+      buffSize = 1024 * 1024
 
 -- | Sets the data associated with a znode (synchronous)
 set :: Zookeeper
@@ -325,14 +334,15 @@
        -> String
        -- ^ The name of the znode expressed as a file name with slashes
        -- separating ancestors of the znode
-       -> (Either ZKError (AclList, Stat) -> IO ())
-       -- ^ The callback function
-       -> IO ()
-getAcl (Zookeeper zh) path callback =
-  withCString path $ \pathPtr -> do
-    cAclFn <- wrapAclCompletion callback
-    rc     <- c_zooAGetAcl zh pathPtr cAclFn nullPtr
-    unless (isZOK rc) (callback $ Left (toZKError rc))
+       -> IO (Either ZKError (AclList, Stat))
+getAcl (Zookeeper zh) path =
+  withCString path $ \pathPtr ->
+    allocaAclVec $ \aclVecPtr ->
+      allocaStat $ \statPtr -> do
+        rc <- c_zooGetAcl zh pathPtr aclVecPtr statPtr
+        if (isZOK rc)
+          then fmap Right $ liftM2 (,) (toAclList aclVecPtr) (toStat statPtr)
+          else return (Left $ toZKError rc)
 
 -- | Specify application credentials (asynchronous)
 --
@@ -369,16 +379,7 @@
 
 -- $description
 --
--- This library provides haskell bindings for zookeeper c-library. The
--- underlying library exposes two classes of functions: synchronous
--- and asynchronous. Whenever possible the synchronous functions are
--- used.
---
--- The reason we do not always use the synchronous version is that it
--- requires the caller to allocate memory and currently it is
--- impossible to know (at least I could not figure it) how much memory
--- should be allocated. The asynchronous version has no such problem
--- as it manages memory internally.
+-- This library provides haskell bindings for zookeeper c-library (mt).
 
 -- $example
 --
@@ -397,8 +398,8 @@
 -- >     takeMVar mvar >>= print
 -- >     where
 -- >       watcher mvar zh _ ConnectedState _ =
--- >         create zh "/foobar" Nothing OpenAclUnsafe [] $ \_ ->
--- >           getChildren zh "/" Nothing (putMVar mvar)
+-- >         void $ create zh "/foobar" Nothing OpenAclUnsafe []
+-- >         getChildren zh "/" Nothing >>= putMVar mvar
 
 -- $notes
 --   * Watcher callbacks must never block;
diff --git a/src/Database/Zookeeper/CApi.hsc b/src/Database/Zookeeper/CApi.hsc
--- a/src/Database/Zookeeper/CApi.hsc
+++ b/src/Database/Zookeeper/CApi.hsc
@@ -34,20 +34,20 @@
        ( -- * C to Haskell
          toStat
        , toState
+       , toAclList
        , toZKError
        , allocaStat
        , toClientId
+       , toStringList
+       , allocaAclVec
+       , allocaStrVec
          -- * Haskell to C
        , withAclList
        , wrapWatcher
        , fromLogLevel
        , fromCreateFlag
        , fromCreateFlags
-       , wrapAclCompletion
-       , wrapDataCompletion
        , wrapVoidCompletion
-       , wrapStringCompletion
-       , wrapStringsCompletion
          -- * Error handling
        , tryZ
        , isZOK
@@ -55,31 +55,30 @@
        , whenZOK
          -- * C functions
        , c_zooSet2
-       , c_zooAWGet
+       , c_zooWGet
        , c_zooState
        , c_zooDelete
        , c_zooSetAcl
-       , c_zooAGetAcl
-       , c_zooACreate
+       , c_zooCreate
+       , c_zooGetAcl
        , c_zooAddAuth
        , c_zooWExists
        , c_zooClientId
        , c_zookeeperInit
-       , c_zookeeperClose
        , c_zooSetWatcher
+       , c_zookeeperClose
        , c_zooRecvTimeout
        , c_isUnrecoverable
-       , c_zooAWGetChildren
+       , c_zooWGetChildren
        , c_zooSetDebugLevel
        ) where
 
 #include <zookeeper.h>
 
-import           Foreign.C
-import           Foreign.Safe
-import qualified Data.ByteString as B
-import           Control.Applicative
-import           Database.Zookeeper.Types
+import Foreign.C
+import Foreign.Safe
+import Control.Applicative
+import Database.Zookeeper.Types
 
 tryZ :: IO CInt -> IO a -> IO (Either ZKError a)
 tryZ zkIO nextIO = do
@@ -183,12 +182,18 @@
                    <*> (fmap toPerms ((#peek struct ACL, perms) ptr))
         buildList (acl : acc) (n-1) (ptr `plusPtr` (#size struct ACL))
 
+allocaStrVec :: (Ptr CStrVec -> IO a) -> IO a
+allocaStrVec = allocaBytes (#size struct String_vector)
+
+allocaAclVec :: (Ptr CAclVec -> IO a) -> IO a
+allocaAclVec = allocaBytes (#size struct ACL_vector)
+
 withAclList :: AclList -> (Ptr CAclVec -> IO a) -> IO a
 withAclList CreatorAll cont    = cont c_zooCreatorAclAll
 withAclList OpenAclUnsafe cont = cont c_zooOpenAclUnsafe
 withAclList ReadAclUnsafe cont = cont c_zooReadAclUnsafe
 withAclList (List acls) cont   =
-  allocaBytes (#size struct ACL_vector) $ \aclvPtr -> do
+  allocaAclVec $ \aclvPtr -> do
     (#poke struct ACL_vector, count) aclvPtr count
     allocaBytes (count * (#size struct ACL)) $ \aclPtr -> do
       (#poke struct ACL_vector, data) aclvPtr aclPtr
@@ -258,34 +263,6 @@
             else fmap Just (peekCString cpath)
   fn (Zookeeper zh) event state path
 
-wrapAclCompletion :: AclCompletion -> IO (FunPtr CAclCompletionFn)
-wrapAclCompletion fn =
-  c_aclCompletionFn $ \rc aclPtr statPtr _ ->
-    fn =<< (onZOK rc $ do
-      aclList <- toAclList aclPtr
-      stat    <- toStat statPtr
-      return (aclList, stat))
-
-wrapDataCompletion :: DataCompletion -> IO (FunPtr CDataCompletionFn)
-wrapDataCompletion fn =
-  c_dataCompletionFn $ \rc valPtr valLen statPtr _ ->
-    fn =<< (onZOK rc $ do
-      stat <- toStat statPtr
-      if (valLen == -1)
-        then return (Nothing, stat)
-        else fmap (\s -> (Just s, stat)) (B.packCStringLen (valPtr, fromIntegral valLen)))
-
-wrapStringCompletion :: StringCompletion -> IO (FunPtr CStringCompletionFn)
-wrapStringCompletion fn =
-  c_stringCompletionFn $ \rc strPtr _ ->
-    fn =<< (onZOK rc $ do
-      peekCString strPtr)
-
-wrapStringsCompletion :: StringsCompletion -> IO (FunPtr CStringsCompletionFn)
-wrapStringsCompletion fn =
-  c_stringsCompletionFn $ \rc strvPtr _ ->
-    fn =<< (onZOK rc (toStringList strvPtr))
-
 wrapVoidCompletion :: VoidCompletion -> IO (FunPtr CVoidCompletionFn)
 wrapVoidCompletion fn =
   c_voidCompletionFn $ \rc _ -> (fn =<< onZOK rc (return ()))
@@ -295,22 +272,6 @@
                  -> IO (FunPtr CWatcherFn)
 
 foreign import ccall safe "wrapper"
-  c_dataCompletionFn :: CDataCompletionFn
-                        -> IO (FunPtr CDataCompletionFn)
-
-foreign import ccall safe "wrapper"
-  c_stringsCompletionFn :: CStringsCompletionFn
-                        -> IO (FunPtr CStringsCompletionFn)
-
-foreign import ccall safe "wrapper"
-  c_stringCompletionFn :: CStringCompletionFn
-                       -> IO (FunPtr CStringCompletionFn)
-
-foreign import ccall safe "wrapper"
-  c_aclCompletionFn :: CAclCompletionFn
-                    -> IO (FunPtr CAclCompletionFn)
-
-foreign import ccall safe "wrapper"
   c_voidCompletionFn :: CVoidCompletionFn
                      -> IO (FunPtr CVoidCompletionFn)
 
@@ -329,8 +290,8 @@
 foreign import ccall safe "zookeeper.h zoo_set_watcher"
   c_zooSetWatcher :: Ptr CZHandle -> FunPtr CWatcherFn -> IO ()
 
-foreign import ccall safe "zookeeper.h zoo_acreate"
-  c_zooACreate :: Ptr CZHandle -> CString -> CString -> CInt -> Ptr CAclVec -> CInt -> FunPtr CStringCompletionFn -> Ptr () -> IO CInt
+foreign import ccall safe "zookeeper.h zoo_create"
+  c_zooCreate :: Ptr CZHandle -> CString -> CString -> CInt -> Ptr CAclVec -> CInt -> CString -> CInt -> IO CInt
 
 foreign import ccall safe "zookeeper.h zoo_delete"
   c_zooDelete :: Ptr CZHandle -> CString -> CInt -> IO CInt
@@ -356,20 +317,20 @@
 foreign import ccall safe "zookeeper.h zoo_set_debug_level"
   c_zooSetDebugLevel :: CInt -> IO ()
 
-foreign import ccall safe "zookeeper.h zoo_aget_acl"
-  c_zooAGetAcl :: Ptr CZHandle -> CString -> FunPtr CAclCompletionFn -> Ptr () -> IO CInt
+foreign import ccall safe "zookeeper.h zoo_get_acl"
+  c_zooGetAcl :: Ptr CZHandle -> CString -> Ptr CAclVec -> Ptr CStat -> IO CInt
 
 foreign import ccall safe "zookeeper.h zoo_set_acl"
   c_zooSetAcl :: Ptr CZHandle -> CString -> CInt -> Ptr CAclVec -> IO CInt
 
-foreign import ccall safe "zookeeper.h zoo_awget"
-  c_zooAWGet :: Ptr CZHandle -> CString -> FunPtr CWatcherFn -> Ptr () -> FunPtr CDataCompletionFn -> Ptr () -> IO CInt
+foreign import ccall safe "zookeeper.h zoo_wget"
+  c_zooWGet :: Ptr CZHandle -> CString -> FunPtr CWatcherFn -> Ptr () -> CString -> Ptr CInt -> Ptr CStat -> IO CInt
 
 foreign import ccall safe "zookeeper.h zoo_set2"
   c_zooSet2 :: Ptr CZHandle -> CString -> CString -> CInt -> CInt -> Ptr CStat -> IO CInt
 
-foreign import ccall safe "zookeeper.h zoo_awget_children"
-  c_zooAWGetChildren :: Ptr CZHandle -> CString -> FunPtr CWatcherFn -> Ptr () -> FunPtr CStringsCompletionFn -> Ptr () -> IO CInt
+foreign import ccall safe "zookeeper.h zoo_wget_children"
+  c_zooWGetChildren :: Ptr CZHandle -> CString -> FunPtr CWatcherFn -> Ptr () -> Ptr CStrVec -> IO CInt
 
 foreign import ccall safe "zookeeper.h &ZOO_CREATOR_ALL_ACL"
   c_zooCreatorAclAll :: Ptr CAclVec
diff --git a/src/test-zookeeper.hs b/src/test-zookeeper.hs
--- a/src/test-zookeeper.hs
+++ b/src/test-zookeeper.hs
@@ -62,35 +62,30 @@
 testExists zh = testGroup "exists"
   [ testCase "exists after create" $ do
       let path = chroot "/testExists#1"
-      mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        exists zh path Nothing >>= putMVar mvar . either (const False) (const True))
-      takeMVar mvar @? "== Right _"
+      create zh path Nothing OpenAclUnsafe []
+      exists zh path Nothing >>= (@? "== Right _") . (either (const False) (const True))
   , testCase "exists without znode" $ do
       let path = chroot "/testExists#2"
-      mvar <- newEmptyMVar
       exists zh path Nothing >>= (@?= Left NoNodeError)
   , testCase "exists(watcher) and create" $ do
       let path = chroot "/testExists#3"
       mvar <- newEmptyMVar
       exists zh path (Just $ watcher mvar) >>= (@?= Left NoNodeError)
-      create zh path Nothing OpenAclUnsafe [] (const $ return ())
+      create zh path Nothing OpenAclUnsafe []
       takeMVar mvar >>= (@?= (CreatedEvent, Just path))
   , testCase "exists(watcher) and set" $ do
       let path = chroot "/testExists#4"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ -> do
-        exists zh path (Just $ watcher mvar)
-        set zh path Nothing Nothing
-        return ())
+      create zh path Nothing OpenAclUnsafe []
+      exists zh path (Just $ watcher mvar)
+      set zh path Nothing Nothing
       takeMVar mvar >>= (@?= (ChangedEvent, Just path))
   , testCase "exists(watcher) and delete" $ do
       let path = chroot "/testExists#5"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ -> do
-        exists zh path (Just $ watcher mvar)
-        delete zh path Nothing
-        return ())
+      create zh path Nothing OpenAclUnsafe []
+      exists zh path (Just $ watcher mvar)
+      delete zh path Nothing
       takeMVar mvar >>= (@?= (DeletedEvent, Just path))
   ]
     where
@@ -99,32 +94,28 @@
 testGet zh = testGroup "get"
   [ testCase "get without znode" $ do
       let path = chroot "/testGet#1"
-      mvar <- newEmptyMVar
-      get zh path Nothing (putMVar mvar)
-      takeMVar mvar >>= (@?= Left NoNodeError)
+      get zh path Nothing >>= (@?= Left NoNodeError)
   , testCase "create(nodata) and get" $ do
       let path = chroot "/testGet#2"
-      mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        get zh path Nothing (putMVar mvar . either (const False) (isNothing . fst)))
-      takeMVar mvar @? "== Right (Nothing, _)"
+      create zh path Nothing OpenAclUnsafe []
+      get zh path Nothing >>= (@? "== Right (Nothing, _)") . (either (const False) (isNothing . fst))
   , testCase "create(data) and get" $ do
       let path = chroot "/testGet#3"
-      mvar <- newEmptyMVar
-      create zh path (Just "foobar") OpenAclUnsafe [] (\_ ->
-        get zh path Nothing (putMVar mvar . either (const False) ((== Just "foobar") . fst)))
-      takeMVar mvar @? "== Right (Just \"foobar\", _)"
+      create zh path (Just "foobar") OpenAclUnsafe []
+      get zh path Nothing >>= (@? "== Right (Just \"foobar\", _)") . (either (const False) ((== Just "foobar") . fst))
   , testCase "get(watcher) and set" $ do
       let path = chroot "/testGet#4"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        get zh path (Just $ watcher mvar) (\_ -> set zh path Nothing Nothing >> return ()))
+      create zh path Nothing OpenAclUnsafe []
+      get zh path (Just $ watcher mvar)
+      set zh path Nothing Nothing
       takeMVar mvar >>= (@?= (ChangedEvent, Just path))
   , testCase "get(watcher) and delete" $ do
       let path = chroot "/testGet#5"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        get zh path (Just $ watcher mvar) (\_ -> delete zh path Nothing >> return ()))
+      create zh path Nothing OpenAclUnsafe []
+      get zh path (Just $ watcher mvar)
+      delete zh path Nothing
       takeMVar mvar >>= (@?= (DeletedEvent, Just path))
   ]
     where
@@ -133,48 +124,39 @@
 testOwnsEphemeral zh = testGroup "ownsEphemeral"
   [ testCase "get ephemeral" $ do
     let path = chroot "/testGet#6"
-    mvar <- newEmptyMVar
-    create zh path Nothing OpenAclUnsafe [Ephemeral] (\_ ->
-      get zh path Nothing (\(Right (_, stat)) -> do
-        myId <- getClientId zh
-        putMVar mvar =<< ownsEphemeral myId stat))
-    takeMVar mvar @? "owns ephemeral"
+    create zh path Nothing OpenAclUnsafe [Ephemeral]
+    (Right (_, stat)) <- get zh path Nothing
+    myId <- getClientId zh
+    ownsEphemeral myId stat @? "owns ephemeral"
   ]
 
 testGetChildren zh = testGroup "getChildren"
   [ testCase "getChildren without znode" $ do
       let path = chroot "/testGetChildren#1"
-      mvar <- newEmptyMVar
-      getChildren zh path Nothing (putMVar mvar)
-      takeMVar mvar >>= (@?= Left NoNodeError)
+      getChildren zh path Nothing >>= (@?= Left NoNodeError)
   , testCase "getChildren after create" $ do
       let path = chroot "/testGetChildren#2"
-      mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        getChildren zh path Nothing (putMVar mvar))
-      takeMVar mvar >>= (@?= Right [])
+      create zh path Nothing OpenAclUnsafe []
+      getChildren zh path Nothing >>= (@?= Right [])
   , testCase "getChildren with one child" $ do
       let path = chroot "/testGetChildren#3"
-      mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        create zh (path ++ "/1") Nothing OpenAclUnsafe [] (\_ ->
-          getChildren zh path Nothing (putMVar mvar)))
-      takeMVar mvar >>= (@?= Right ["1"])
+      create zh path Nothing OpenAclUnsafe []
+      create zh (path ++ "/1") Nothing OpenAclUnsafe []
+      getChildren zh path Nothing >>= (@?= Right ["1"])
   , testCase "getChildren(watcher) and create child" $ do
       let path = chroot "/testGetChildren#4"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        getChildren zh path (Just $ watcher mvar) (\_ ->
-          create zh (path ++ "/1") Nothing OpenAclUnsafe [] (const $ return ())))
+      create zh path Nothing OpenAclUnsafe []
+      getChildren zh path (Just $ watcher mvar)
+      create zh (path ++ "/1") Nothing OpenAclUnsafe []
       takeMVar mvar >>= (@?= (ChildEvent, Just path))
   , testCase "getChildren(watcher) and delete child" $ do
       let path = chroot "/testGetChildren#5"
       mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        create zh (path ++ "/1") Nothing OpenAclUnsafe [] (\_ ->
-          getChildren zh path (Just $ watcher mvar) (\_ -> do
-            delete zh (path ++ "/1") Nothing
-            return ())))
+      create zh path Nothing OpenAclUnsafe []
+      create zh (path ++ "/1") Nothing OpenAclUnsafe []
+      getChildren zh path (Just $ watcher mvar)
+      delete zh (path ++ "/1") Nothing
       takeMVar mvar >>= (@?= (ChildEvent, Just path))
   ]
     where
@@ -183,10 +165,8 @@
 testGetAcl zh = testGroup "getAcl"
   [ testCase "getAcl" $ do
       let path = chroot "/testGetAcl#1"
-      mvar <- newEmptyMVar
-      create zh path Nothing OpenAclUnsafe [] (\_ ->
-        getAcl zh path (putMVar mvar . either (const 0) (countAcls . fst)))
-      takeMVar mvar >>= (@?= 1)
+      create zh path Nothing OpenAclUnsafe []
+      getAcl zh path >>= (@?= 1) . (either (const 0) (countAcls . fst))
   , testCase "getAcl flags" $ do
       let path  = chroot "/testGetAcl#2"
           flags = [ []
@@ -197,12 +177,10 @@
                   , [CanRead, CanAdmin, CanWrite, CanCreate, CanDelete]
                   ]
       forM_ flags $ \flag -> do
-        mvar <- newEmptyMVar
-        create zh path Nothing (List [Acl "world" "anyone" flag]) [] (\_ -> do
-          getAcl zh path (\rc -> do
-            delete zh path Nothing
-            putMVar mvar (either (const []) (getFlags . fst) rc)))
-        takeMVar mvar >>= (@?= flag)
+        create zh path Nothing (List [Acl "world" "anyone" flag]) []
+        rc <- getAcl zh path
+        delete zh path Nothing
+        (either (const []) (getFlags . fst) rc) @?= flag
   ]
     where
       countAcls (List xs) = length xs
@@ -214,25 +192,23 @@
 rmrf :: Zookeeper -> String -> IO ()
 rmrf zh path = do
   let childPath name = path ++ "/" ++ name
-  mvar <- newEmptyMVar
-  getChildren zh path Nothing (putMVar mvar)
-  takeMVar mvar >>= either (const $ return ()) (mapM_ (rmrf zh . childPath))
-  delete zh path Nothing
-  return ()
+  children <- getChildren zh path Nothing
+  case children of
+    Right xs -> mapM_ (rmrf zh . childPath) xs
+    Left _   -> return ()
+  void $ delete zh path Nothing
 
 main :: IO ()
 main = do
   disclaimer
   endpoint   <- getEndpoint
   waitState  <- newEmptyMVar
-  waitCreate <- newEmptyMVar
   withZookeeper endpoint 5000 (Just $ watcher waitState) Nothing $ \zh -> do
     state <- takeMVar waitState
     case state of
       ConnectedState -> do
         rmrf zh (chroot "")
-        create zh (chroot "") Nothing OpenAclUnsafe [] (putMVar waitCreate)
-        takeMVar waitCreate
+        create zh (chroot "") Nothing OpenAclUnsafe []
         defaultMain $ testGroup "Zookeeper" [ testGet zh
                                             , testExists zh
                                             , testGetAcl zh
