GNU bug report logs - #19235
make-fresh-user-module procedure leaks memory

Previous Next

Package: guile;

Reported by: Chris Vine <chris <at> cvine.freeserve.co.uk>

Date: Sun, 30 Nov 2014 23:30:05 UTC

Severity: normal

Full log


Message #8 received at 19235 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: Chris Vine <chris <at> cvine.freeserve.co.uk>
Cc: 19235 <at> debbugs.gnu.org
Subject: Re: bug#19235: make-fresh-user-module procedure leaks memory
Date: Sun, 07 Dec 2014 03:07:43 -0500
Chris Vine <chris <at> cvine.freeserve.co.uk> writes:

> The make-fresh-user-module procedure leaks memory in guile-2.0.11 as
> demonstrated by the attached test case.  [...]
>
> The question which might be asked is "Would any sane person ever want
> to invoke the make-fresh-user-module procedure more than a few times
> in a practical program?".  The answer to this question is "Yes", if
> guile is being used as an extension framework for a C or C++ program,
> and it executes guile extensions as individual tasks, and it is
> necessary that top levels should not to be shared.  The execution of
> tasks concurrently is one such case, but there can be many cases where
> isolated top levels are desirable for tasks executed serially also.

Unfortunately, Guile modules cannot be garbage collected.  The problem
is that modules are usually referenced by name, not by direct pointers.
Every module must have a name, due to the way our macro expander works.
Modules created by 'make-module' or 'make-fresh-user-module' are named
using gensyms.

We maintain a global map from module names to module objects, and we can
never safely delete from this map, because we cannot prove that the
module name won't be looked up in the future.

I agree that your use case is reasonable.  I'll think about how we might
allow unnamed modules to be collected, but I'm afraid it might be quite
difficult.

In the meantime, I wrote a procedure that uses undocumented interfaces
to forcefully delete a module from the name->module map.  However, I
must emphasize that this procedure is likely to break in a future
version of Guile.  However, it should work in the 2.0.x series.

--8<---------------cut here---------------start------------->8---
;; WARNING: Uses undocumented interfaces; NOT FUTURE PROOF!!
;; This needs (srfi srfi-1)
(define (delete-module! module)
  (let* ((name (module-name module))
         (last-name (last name))
         (parent-name (drop-right name 1))
         (parent (resolve-module parent-name #f))
         (var (module-variable parent last-name)))
    (when (and var
               (variable-bound? var)
               (eqv? (variable-ref var) module))
      (hashq-remove! (module-obarray parent) last-name))
    (hashq-remove! (module-submodules parent) last-name)
    #f))
--8<---------------cut here---------------end--------------->8---

I should mention that creating new modules with 'make-fresh-user-module'
is not thread safe, nor is the procedure above.  Both of them mutate the
same name->module map.  For now, I recommend protecting calls to both of
them with a mutex.

      Mark




This bug report was last modified 8 years and 355 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.