• Kirill Smelkov's avatar
    libgolang: tests: It is not safe to capture by reference in go(<lambda>) · 44737253
    Kirill Smelkov authored
    When lambda captures stack-resided variable by reference, it actually
    remembers address of that variable and inside lambda code dereferences
    that address on variable use. The lifetime of all spawned goroutines in
    libgolang_test is subset of test function driver lifetime, so capturing
    by reference should be safe in that situation on the first glance.
    However for that to work, it is required that stacks of both goroutines
    - the main goroutine and spawned goroutine - must be live at the same
    time, so that spawned goroutine could safely retrieve a
    reference-captured variable located on the main goroutine stack.
    
    This works for thread runtime, but is known not to work for gevent
    runtime, where inactive goroutine stack is swapped onto heap and is
    generally considered "dead" while that goroutine is parked (see
    "Implementation note" in 3b241983 "Port/move channels to C/C++/Pyx" for
    details about this).
    
    -> Fix the test by capturing by value in lambdas. What we capture is
    usually chan<T> object, which itself is a pointer, so it should not make
    a big difference in efficiency. It is also more safe to capture channels
    by value, since that automatically incref/decref them and adds extra
    protection wrt lifetime management bugs.
    
    NOTE sending/receiving via channels from/to stack-based variables is
    always safe - for both thread and gevent runtimes, as channels
    implementation explicitly cares for this to work. Once again
    "Implementation note" in 3b241983 has the details.
    44737253
libgolang_test.cpp 7.72 KB