kim / leveldb-haskell

Haskell bindings to LevelDB (https://github.com/google/leveldb)
BSD 3-Clause "New" or "Revised" License
66 stars 50 forks source link

RocksDB segfaults on many puts #31

Closed AlexeyRaga closed 8 years ago

AlexeyRaga commented 8 years ago

Pretty much any of the examples can fail when multiple sequential puts are performed (at least on Mac OS X). For example, adding this fragment to the comparator example and running the compiled code 3-5 times reproduces this issue:

    let write = uncurry $ put db def
    let input = [(bs, bs) | x <- ['a' .. 'z'], let bs = singleton x]
    mapM_ write input

The full example code then would be:

module Main where

import           Control.Monad.IO.Class     (liftIO)
import           Data.Default
import           Database.LevelDB
import qualified Database.LevelDB.Streaming as S
import Data.ByteString.Char8 (singleton)

customComparator :: Comparator
customComparator = Comparator compare

main :: IO ()
main = runResourceT $ do
    db <- open "/tmp/lvlcmptest"
               defaultOptions{ createIfMissing = True
                             , comparator = Just customComparator
                             }

    put db def "zzz" ""
    put db def "yyy" ""
    put db def "xxx" ""

    let write = uncurry $ put db def

    let input = [(bs, bs) | x <- ['a' .. 'z'], let bs = singleton x]
    mapM_ write input

    withIterator db def $ \iter -> liftIO $
            S.toList (S.entrySlice iter S.AllKeys S.Asc)
        >>= print

    return ()

And this is the response I get from running this code (as you can see it star failing after couple of runs):

$ leveldb-example-comparator
[("a","a"),("b","b"),("c","c"),("d","d"),("e","e"),("f","f"),("g","g"),("h","h"),("i","i"),("j","j"),("k","k"),("l","l"),("m","m    "),("n","n"),("o","o"),("p","p"),("q","q"),("r","r"),("s","s"),("t","t"),("u","u"),("v","v"),("w","w"),("x","x"),("xxx",""),("y    ","y"),("yyy",""),("z","z"),("zzz","")]
$ leveldb-example-comparator
[("a","a"),("b","b"),("c","c"),("d","d"),("e","e"),("f","f"),("g","g"),("h","h"),("i","i"),("j","j"),("k","k"),("l","l"),("m","m    "),("n","n"),("o","o"),("p","p"),("q","q"),("r","r"),("s","s"),("t","t"),("u","u"),("v","v"),("w","w"),("x","x"),("xxx",""),("y    ","y"),("yyy",""),("z","z"),("zzz","")]
$ leveldb-example-comparator
[("a","a"),("b","b"),("c","c"),("d","d"),("e","e"),("f","f"),("g","g"),("h","h"),("i","i"),("j","j"),("k","k"),("l","l"),("m","m    "),("n","n"),("o","o"),("p","p"),("q","q"),("r","r"),("s","s"),("t","t"),("u","u"),("v","v"),("w","w"),("x","x"),("xxx",""),("y    ","y"),("yyy",""),("z","z"),("zzz","")]
$ leveldb-example-comparator
[1]    63389 segmentation fault
$ leveldb-example-comparator
leveldb-example-comparator: schedule: re-entered unsafely.
   Perhaps a 'foreign import unsafe' should be 'safe'?
[1]    63400 segmentation fault
$ leveldb-example-comparator
leveldb-example-comparator: schedule: re-entered unsafely.
   Perhaps a 'foreign import unsafe' should be 'safe'?
AlexeyRaga commented 8 years ago

As far as I can see from some point put starts returning a random unreadable string in its errptr. But I have no idea of why it happens and why the database gets corrupted after when it happens.

kim commented 8 years ago

You will need to link against the threaded runtime if you want allow native leveldb to call back into haskell.

This has been reported before (#27), so I'm closing this one as duplicate. Feel free to reopen if you have a better solution.