GithubHelp home page GithubHelp logo

Error when deserializing about spicerack HOT 4 CLOSED

jackrusher avatar jackrusher commented on August 17, 2024
Error when deserializing

from spicerack.

Comments (4)

jackrusher avatar jackrusher commented on August 17, 2024

Would it be possible to provide a failing test case?

from spicerack.

plexus avatar plexus commented on August 17, 2024

I dug into this a bit more. Here's an example failing test case

(deftest storing-bad-values
  (testing "fail early when storing functions"
    (cleanup)
    (with-open [db (open-database test-filename)]
      (let [hm (open-hashmap db "test-hashmap")]
        (is (thrown? Throwable (do (put! hm :lambda (fn []))
                                   ;; it's the "get" that triggers an error
                                   ;; (get hm :lambda)
                                   )))))))

The problem is that Clojure functions are Serializable (I found this somewhat surprising, but it turns out to be true), and so MapDB stores them as a Java Object. When it pulls them out and tries to deserialize them, it does its own class lookup on the function "class", something like "spicerack.core_test$eval20554$fn__20555", which fails.

I'm happy to call this "garbage-in-garbage-out" and close the issue. It's just unfortunate that the problem is only triggered when reading, thus rendering your database (at least partially) unusable.

A possible "solution" could be

(defn put!
  "Write the key/value pair (`k`,`v`) to hashmap `m`. Returns v."
  [m k v]
  (assert (not (instance? clojure.lang.AFunction v)) "The stored value should not be a function.")
  (.put m k v)
  v)

(You have to check for AFunction here, IFn or AFn include things like keywords and maps.)


For the curious: yes Clojure functions are actually serializable. No idea how will this works across reboots or across runtimes though 😄

((let [serialized
       (let [baos (java.io.ByteArrayOutputStream.)
             oos (java.io.ObjectOutputStream. baos)]
         (.writeObject oos (fn [] :sentinel))
         (.toByteArray baos))]

   (let [bais (java.io.ByteArrayInputStream. serialized)
         ois (java.io.ObjectInputStream. bais)]
     (.readObject ois))))
;;=> :sentinel

from spicerack.

jackrusher avatar jackrusher commented on August 17, 2024

Thanks for the more detailed bug report!

The Clojure compiler generates Java classes that it then pushes out to class files as it goes, even for anonymous functions. My guess is that they are Serializable to facilitate that process. Sadly, that doesn't help us here, because when they are re-loaded from the DB they are orphaned from the other stuff that would be in those class files. 😿

A workaround for cases where this functionality is desired is to use serializable-fn for those functions.

I agree with you that it's unfortunate that someone can put rubbish in their database this way, but at the same time I'm not willing to add the overhead of a Java reflection call to every put. We should document this case instead.

from spicerack.

plexus avatar plexus commented on August 17, 2024

That makes sense.

from spicerack.

Related Issues (8)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.