libgolang/gevent: Fix io_read deadlock and io_read/io_write potential data corruption
When underlying pygfobj is FileObjectThread its .readinto() leads to deadlock because it is no cooperative(*). This manifests as test_pyx_os_pipe_cpp hang when run by gpython on windows. -> Workaround this by reading first into intermediate buffer and then copying data to buffer that user provided. After this the deadlock is gone but test_pyx_os_pipe_cpp starts to fail and crash randomly. That's because similarly to channels we need to care and not access a buffer if it is located on stack and owning greenlet is inactive. Because when a greenlet is inactive, its stack is reused by another active greenlet and writing/reading to on-stack memory accesses that second greenlet stack, corrupting it on write. -> do the same what we do in chan operations: use intermediate on-heap buffer to protect original user's buffer to be accesses because it might be located on stack. That's what actually happens in test_pyx_os_pipe_cpp where two goroutines read and write to each other via pipe and using on-stack located buffers. And becuase on windows pipes, like regular files, are wrapped with FileObjectThread, when reading greenlet becomes suspended waiting for read reasul, it will be another greenlet to run on its stack, write to another end of a pipe, wakeup IO thread, which will write the data to requested buffer on G1 stack and oops - it was G2 there. (*) see https://github.com/gevent/gevent/pull/1948 for details
Showing
Please register or sign in to comment