unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Antoine Latter <aslatter@gmail.com>
To: Ben Gamari <bgamari.foss@gmail.com>
Cc: Bart Massey <bart@cs.pdx.edu>,
	glasgow-haskell-users@haskell.org, notmuch@notmuchmail.org,
	haskell-cafe@haskell.org
Subject: Re: Bug in GC's ordering of ForeignPtr finalization?
Date: Sun, 28 Aug 2011 22:26:05 -0500	[thread overview]
Message-ID: <CAKjSnQGPRu7nWbLiuLX4niUyRNNbziNwBsX1s3+WyYx+9aTpcw@mail.gmail.com> (raw)
In-Reply-To: <87pqjprzu2.fsf@gmail.com>

On Sun, Aug 28, 2011 at 4:27 PM, Ben Gamari <bgamari.foss@gmail.com> wrote:
> On Tue, 16 Aug 2011 12:32:13 -0400, Ben Gamari <bgamari.foss@gmail.com> wrote:
>> It seems that the notmuch-haskell bindings (version 0.2.2 built against
>> notmuch from git master; passes notmuch-test) aren't dealing with memory
>> management properly. In particular, the attached test code[1] causes
>> talloc to abort.  Unfortunately, while the issue is consistently
>> reproducible, it only occurs with some queries (see source[1]). I have
>> been unable to establish the exact criterion for failure.
>>
>> It seems that the crash is caused by an invalid access to a freed Query
>> object while freeing a Messages object (see Valgrind trace[3]). I've
>> taken a brief look at the bindings themselves but, being only minimally
>> familiar with the FFI, there's nothing obviously wrong (the finalizers
>> passed to newForeignPtr look sane). I was under the impression that
>> talloc was reference counted, so the Query object shouldn't have been
>> freed unless if there was still a Messages object holding a
>> reference. Any idea what might have gone wrong here?  Thanks!
>>
> After looking into this issue in a bit more depth, I'm even more
> confused. In fact, I would not be surprised if I have stumbled into a
> bug in the GC. It seems that the notmuch-haskell bindings follow the
> example of the python bindings in that child objects keep references to
> their parents to prevent the garbage collector from releasing the
> parent, which would in turn cause talloc to free the child objects,
> resulting in odd behavior when the child objects were next accessed. For
> instance, the Query and Messages objects are defined as follows,
>
>    type MessagesPtr = ForeignPtr S__notmuch_messages
>    type MessagePtr = ForeignPtr S__notmuch_message
>    newtype Query = Query (ForeignPtr S__notmuch_query)
>    data MessagesRef = QueryMessages { qmpp :: Query, msp :: MessagesPtr }
>                     | ThreadMessages { tmpp :: Thread, msp :: MessagesPtr }
>                     | MessageMessages { mmspp :: Message, msp :: MessagesPtr }
>    data Message = MessagesMessage { msmpp :: MessagesRef, mp :: MessagePtr }
>                 | Message { mp :: MessagePtr }
>    type Messages = [Message]
>

One problem you might be running in to is that the optimization passes
can notice that a function isn't using all of its arguments, and then
it won't pass them. These even applies if the arguments are bound
together in a record type.

So if you have a record type:

> data QueryResult = QR {qrQueryPtr :: ForeignPtr (), qrResultPointer :: Ptr ()}

and a function:

> processQueryResult :: QueryResult -> IO (...)

If the function doesn't use the 'qrQueryPointer' part of the record,
the compiler may not even pass it in. This might run the finalizer for
the foreign pointer earlier than you expect. If the result pointer is
a part of the query foreign pointer, you're in trouble.

I'm not sure if this is what's happening, but it sounds like it could be.

If this is the case you might want to build some helper functions
using the function 'touchForeignPtr', which does nothing other than
make it look like the foreign pointer is still in use. In my example
it might be something like:

> withQueryResultPtr :: QueryResult -> (Ptr QueryResult -> IO a) -> IO a
> withQueryResultPtr qr k = do
>    x <- k (qrQueryPtr qr)
>    touchForeignPtr (qrResultPointer qr)
>    return x

Antoine

  reply	other threads:[~2011-08-29  3:26 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-16 16:32 Memory management issue in notmuch-haskell bindings Ben Gamari
2011-08-28 21:27 ` Bug in GC's ordering of ForeignPtr finalization? Ben Gamari
2011-08-29  3:26   ` Antoine Latter [this message]
2011-08-29  3:47     ` Ben Gamari
2011-08-29  4:03       ` Antoine Latter
     [not found]   ` <20110829183010.GA2605@24f89f8c-e6a1-4e75-85ee-bb8a3743bb9f>
2011-08-29 20:30     ` Memory management practices Ben Gamari
2011-09-07 20:36       ` Ben Gamari
2011-09-08  2:48         ` Austin Clements
2011-09-08  3:05           ` Austin Clements
2011-09-08 13:50             ` Sebastian Spaeth
2011-09-08 15:15               ` Austin Clements
2011-09-09  9:27                 ` Sebastian Spaeth
2011-09-09 17:53                   ` Austin Clements
2011-09-11 21:47                     ` Ben Gamari
2011-09-12  2:18                       ` Austin Clements
2011-09-12 12:30                     ` Sebastian Spaeth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAKjSnQGPRu7nWbLiuLX4niUyRNNbziNwBsX1s3+WyYx+9aTpcw@mail.gmail.com \
    --to=aslatter@gmail.com \
    --cc=bart@cs.pdx.edu \
    --cc=bgamari.foss@gmail.com \
    --cc=glasgow-haskell-users@haskell.org \
    --cc=haskell-cafe@haskell.org \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).