# New Ticket Created by  Leopold Toetsch 
# Please include the string:  [perl #19622]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=19622 >


I did write:

[1] which BTW seems bogus to me: pool_compact() may be called (when 
there is enough reclaimable space), without having a DOD run immediately 
before it. So e.g. the on_free_list flag might not reflect current usage 
of a buffer.

Here is a program showing more problems with the current implementation:

        set S0, "abcdefghij"
        set I0, 0
lp: 
repeat S1, S0, 5000
        ne S0, "abcdefghij", nok
        substr S2, S1, 1, 1
        ne S2, "b", nok
        inc I0
        lt I0, 1000, lp
        print "ok\n"
        end
nok: 
print "nok\n"
        print S0
        print " - "
        print S1
        print "\n"
        end

The substr makes a COW reference of S1, which doesn't set 
pool->guaranteed_reclaimable, so when above is run without --gc-debug, 
pool->compact gets nether called and the program dies with SIGSEGV - the 
real reason is a NULL pointer returned from malloc().

--gc-debug does a DOD run + an unconditional compact_pool, so the 
program runs fine.

A proposed change could look like attached patch:
- die when malloc returns zero (IMHO we can't recover)
- always call do_dod_run before compact_pool
- when possibly_reclaimable reaches a certain amount, always compact the 
pool - the reclaim_factor (currently 20%) doesn't really matter, it just 
allows that the pool gets compacted sooner or later - it is used now as 
a probablity meaning 20% of COWed strings might be reclaimable.

leo


-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/46630/36629/d8ca8a/resources.c.patch

--- resources.c Fri Dec 27 10:34:28 2002
+++ /home/lt/src/parrot-leo/resources.c Tue Dec 31 14:26:26 2002
@@ -45,6 +45,8 @@
     new_block = mem_sys_allocate_zeroed(sizeof(struct Memory_Block) +
             alloc_size + 32);
     if (!new_block) {
+        fprintf(stderr, "out of mem allocsize = %d\n", (int)alloc_size+32);
+        exit(1);
         return NULL;
     }
 
@@ -110,25 +112,25 @@
         }
     }
     if (pool->top_block->free < size) {
+        Parrot_do_dod_run(interpreter);
         /* Compact the pool if allowed and worthwhile */
         if (pool->compact) {
             /* don't bother reclaiming if its just chicken feed */
-            if ((pool->possibly_reclaimable + pool->guaranteed_reclaimable) / 2
-                    > (size_t)(pool->total_allocated * pool->reclaim_factor)
+            if (pool->possibly_reclaimable * pool->reclaim_factor
+                    > size
                     /* don't bother reclaiming if it won't even be enough */
-                    && (pool->guaranteed_reclaimable > size)
+                    || (pool->guaranteed_reclaimable > size)
                     ) {
                 (*pool->compact) (interpreter, pool);
             }
-            else {
-                Parrot_do_dod_run(interpreter);
-            }
 
         }
         if (pool->top_block->free < size) {
             alloc_new_block(interpreter, size, pool);
             interpreter->mem_allocs_since_last_collect++;
             if (pool->top_block->free < size) {
+                fprintf(stderr, "out of mem\n");
+                exit(1);
                 return NULL;
             }
         }

Reply via email to