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