Home - Summaries: (main) : (py3.11) : Everything - Nightly builds - Benchmarks - RPython - Builders - About

translator/c/test/test_standalone.py::TestThread::()::test_thread_and_gc_with_fork

self = <rpython.translator.c.test.test_standalone.TestThread object at 0x7f8b65405cd0>

    def test_thread_and_gc_with_fork(self):
        # This checks that memory allocated for the shadow stacks of the
        # other threads is really released when doing a fork() -- or at
        # least that the object referenced from stacks that are no longer
        # alive are really freed.
        import time, gc, os
        from rpython.rlib import rthread
        if not hasattr(os, 'fork'):
            py.test.skip("requires fork()")
    
        from rpython.rtyper.lltypesystem import rffi, lltype
        direct_write = rffi.llexternal(
            "write", [rffi.INT, rffi.CCHARP, rffi.SIZE_T], lltype.Void,
            _nowrapper=True)
    
        class State:
            pass
        state = State()
    
        class Cons:
            def __init__(self, head, tail):
                self.head = head
                self.tail = tail
    
        class Stuff:
            def __del__(self):
                p = rffi.str2charp('d')
                one = rffi.cast(rffi.SIZE_T, 1)
                direct_write(rffi.cast(rffi.INT, state.write_end), p, one)
                rffi.free_charp(p)
    
        def allocate_stuff():
            s = Stuff()
            os.write(state.write_end, 'a')
            return s
    
        def run_in_thread():
            for i in range(10):
                state.xlist.append(Cons(123, Cons(456, None)))
                time.sleep(0.01)
            childpid = os.fork()
            return childpid
    
        def bootstrap():
            rthread.gc_thread_start()
            childpid = run_in_thread()
            gc.collect()        # collect both in the child and in the parent
            gc.collect()
            gc.collect()
            if childpid == 0:
                os.write(state.write_end, 'c')   # "I did not die!" from child
            else:
                os.write(state.write_end, 'p')   # "I did not die!" from parent
            rthread.gc_thread_die()
    
        def new_thread():
            ident = rthread.start_new_thread(bootstrap, ())
            time.sleep(0.5)    # enough time to start, hopefully
            return ident
    
        def start_arthreads():
            s = allocate_stuff()
            ident1 = new_thread()
            ident2 = new_thread()
            ident3 = new_thread()
            ident4 = new_thread()
            ident5 = new_thread()
            # wait for 4 more seconds, which should be plenty of time
            time.sleep(4)
            keepalive_until_here(s)
    
        def entry_point(argv):
            os.write(1, "hello world\n")
            state.xlist = []
            state.deleted = 0
            state.read_end, state.write_end = os.pipe()
            x2 = Cons(51, Cons(62, Cons(74, None)))
            # start 5 new threads
            start_arthreads()
            # force freeing
            gc.collect()
            gc.collect()
            gc.collect()
            # return everything that was written to the pipe so far,
            # followed by the final dot.
            os.write(state.write_end, '.')
            result = os.read(state.read_end, 256)
            os.write(1, "got: %s\n" % result)
            return 0
    
>       t, cbuilder = self.compile(entry_point)

translator/c/test/test_standalone.py:1520: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
translator/c/test/test_standalone.py:1240: in compile
    cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
translator/c/genc.py:178: in generate_source
    db = self.build_database()
translator/c/genc.py:102: in build_database
    self.config.translation.reverse_debugger)
translator/c/database.py:64: in __init__
    self.gctransformer = self.gcpolicy.gettransformer(translator, gchooks)
translator/c/gc.py:452: in gettransformer
    return shadowstack.ShadowStackFrameworkGCTransformer(translator, gchooks)
memory/gctransform/framework.py:132: in __init__
    GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
memory/gc/base.py:593: in choose_gc_from_config
    globals(), locals(), [classname])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    # XXX Should find a way to bound the major collection threshold by the
    # XXX total addressable size.  Maybe by keeping some minimarkpage arenas
    # XXX pre-reserved, enough for a few nursery collections?  What about
    # XXX raw-malloced memory?
    
    # XXX try merging old_objects_pointing_to_pinned into
    # XXX old_objects_pointing_to_young (IRC 2014-10-22, fijal and gregor_w)
    import sys
    import os
    import time
    from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, llgroup
    from rpython.rtyper.lltypesystem.lloperation import llop
    from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage
    from rpython.memory.gc.base import GCBase, MovingGCBase
>   from rpython.memory.gc import env
E     File "/build_dir/rpython-linux-x86-64/build/rpython/memory/gc/env.py", line 423
E   SyntaxError: Non-ASCII character '\xe2' in file /build_dir/rpython-linux-x86-64/build/rpython/memory/gc/env.py on line 423, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

memory/gc/incminimark.py:70: SyntaxError
---------- Captured stderr call ----------
[rtyper] specializing: 100 / 462 blocks   (21%)
[rtyper] specializing: 200 / 521 blocks   (38%)
[rtyper] specializing: 300 / 521 blocks   (57%)
[rtyper] specializing: 500 / 653 blocks   (76%)
[rtyper] specializing: 600 / 653 blocks   (91%)
[rtyper] -=- specialized 653 blocks -=-
[rtyper] specializing: 700 / 701 blocks   (99%)
[rtyper] -=- specialized 48 more blocks -=-
[rtyper] -=- specialized 9 more blocks -=-
[rtyper] -=- specialized 4 more blocks -=-
[rtyper] -=- specialized 25 more blocks -=-
builder: rpython-linux-x86-64 build #885
test: translator/c/test/test_standalone/py/TestThread/()/test_thread_and_gc_with_fork