libgolang: tests: It is not safe to capture by reference in go(<lambda>)
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.
Showing
Please register or sign in to comment