The cause of the leak within dump-threads was ##thread-continuation-capture . With the workaround in https://github.com/feeley/gambit/issues/36 applied on it,  ##thread-continuation-capture now works and thus (dump-threads) too.

2013/6/22 Mikael <mikael.rcv@gmail.com>

That was the first time in many years I was aware of a memory leak scenario in a Gambit env.

The leak consisted of 1) https://github.com/feeley/gambit/issues/33 that regards wills not GC:ing if you ran will-execute! on it, for a programmer that one is easily worked around, and then 2) the following problem.

Apart from these two, Gambit works perfectly to my knowing.


Find dump_threads.scm and dump_threads_bug_demo.scm attached. Just launch them like this:

$ gsc
Gambit v4.6.9

> (load "dump_threads.scm") (load "dump_threads_bug_demo.scm") (demo)
"/home/user/dump_threads.scm"
> "/home/user/dump_threads_bug_demo.scm"
> Creating 10000 threads
Waiting for threads to finish
Numbered objects on the heap prior to GC: 10001 - A (##gc) is made here.
Numbered objects on the heap after GC: 1        - All the 10000 threads GC:ed, this is what should happen.
Creating 10000 threads, while doing a bunch of dump-threads calls too
Waiting for threads to finish
Numbered objects on the heap prior to GC: 10003 - Now we do the same test again but while doing a bunch of dump-threads calls
Numbered objects on the heap after GC: 9004     - 9000 of the 1000 threads created became resistent to ##gc and never collect = Memory leak!
>


What happens here is that we see how (dump-threads) invocations *makes ~90% of threads running stuck on the heap and never GC*!


|dump-threads| is a really neat debug tool - so neat everybody should have a copy, that kind of level of neat - how can we make it not trash Gambit like this, but instead completely reliable?




Ordinary dump-threads use example, just so you know what it is about:

$ gsc
Gambit v4.6.9

> (load "dump_threads.scm")
"/home/user/dump_threads.scm"
> (thread-start! (make-thread (lambda () (define myvar 1234) (thread-sleep! 5) (void)) 'first-thread))
#<thread #2 first-thread>
> (thread-start! (make-thread (lambda () (define myvar 5678) (thread-sleep! 5) (void)) 'second-thread))
#<thread #3 second-thread>
> (thread-yield!)
> (dump-threads #t 100 100)
#<thread #1 primordial>
0  loop                            "dump_threads.scm"@111:32       (with-exception-catcher (lambda (...
        result = ##thread-void-action!
        exception? = #f
        end-condvar = '#<condition-variable #4 #f>
        quantum-pre = .02
        loop = (lambda () (letrec ((quantum-pre (thread-quantum (current-thread)))) (thread-quantum-...
        thread = '#<thread #1 primordial>
        display-environment = #t
        max-head = 100
        max-tail = 100
1  dump-thread                     "dump_threads.scm"@124:5        (out)
        out = (lambda () ((letrec ((loop (lambda () (letrec ((quantum-pre (thread-quantum (current-t...
        thread = '#<thread #1 primordial>
        display-environment = #t
        max-head = 100
        max-tail = 100
2  for-each
3  (interaction)                   (console)@5:1                   (dump-threads #t 100 100)

#<thread #2 first-thread>
0  ##thread-sleep!
1  #<procedure #5>                 (console)@2:60                  (thread-sleep! 5)
        myvar = 1234
2  ##thread-start-action!

#<thread #3 second-thread>
0  ##thread-sleep!
1  #<procedure #6>                 (console)@3:60                  (thread-sleep! 5)
        myvar = 5678
2  ##thread-start-action!

>

What it does is to show all running threads including their environment.

So, at least in my frame of reference, a quite central debug tool.

Would be great if we could fix it.


Brgds,
Mikael