[Ecls-list] [RFC PATCH] Fix GC for threads + mprotect signal handling.

Juan Jose Garcia-Ripoll juanjose.garciaripoll at googlemail.com
Mon Jun 1 12:37:00 UTC 2009


On Mon, Jun 1, 2009 at 12:25 PM, Alexander Gavrilov
<angavrilov at gmail.com> wrote:
> When ECL uses mprotect signal handling, it allocates the
> environment structure using mmap; thus it is no longer
> traversed by the GC during collection.

No, it is traversed. See alloc_2.d for the routine that explicitely
traverses all environments. I have avoided using GC_register_roots all
over ECL, concentrating all roots in the code that analyzes the core
data and the per-thread environments. There are two reasons for this
 1) There is a limited number of calls to GC_register_roots and
GC_unregister_roots did not work well before.
 2) Most important, if we use GC_*_roots we need to resort to finalization.

I agree, though, that it is a mistake to wait until a thread is
started to add a process to the list of existing processes. This can
cause data loss if a garbage collection happens before the thread is
started. But a simpler solution would be to move the code that changes
cl_core.processes from mp_process_enable to alloc_process

>        P.P.S. It may be a good idea to allocate the full
>          environment only while the thread is running, and
>          keep persistent pointers in the process object.

I would indeed suggest a different patch, attached to this email,
which does this:

+ Master creates process object
+ Master enables process
    - Thread is started
    - Thread blocks temporarily and add process to cl_core.processes
    - Environment is created and added to the process object (now it
can be traversed)
    - Environment is initialized
    - Code is run
    - Environment is destroyed
    - Process is marked as inactive and removed from cl_core.processes

>        P.S. The finalization part is not tested, because my
>          program never destroys its threads. It also may be
>          a good idea to add only some important fields as
>          roots, but I don't know which exactly these are.

Finalization for environments is not really required -- there are no
resources to be deallocated -- and I still feel that it is extremely
undesirable to rely on it. The mechanism for finalization is pretty
unpredictable and a process might get retained if stored in a circular
structure. That is why I favor the solution before.

Please comment the code. I have tested it with variations of the following

(dotimes (i 20)
    (let* ((n i)(p (mp:make-process)))
     (mp:process-preset p
       #'(lambda (&rest r)
           (format t "~%Entering thread ~D" n) (sleep 0.5)
           (format t "~%Leaving thread ~D" n)))
     (mp:process-enable p)))

Juanjo

-- 
Instituto de Física Fundamental, CSIC
c/ Serrano, 113b, Madrid 28009 (Spain)
http://juanjose.garciaripoll.googlepages.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: threads-patch.diff
Type: application/octet-stream
Size: 5938 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20090601/263f52d9/attachment.obj>


More information about the ecl-devel mailing list