g_subprocess_communicate_async() can deadlock when writing
We're seeing a deadlock in gtk-demo when using g_subprocess_communicate_async() to syntax highlight asynchronously.
The problem is that it calls g_output_stream_splice_async() to write to the child pipe, and that writes in blocks of 8192 bytes (buffer
in g_output_stream_real_splice
). Eventually, after many writes we end up in g_unix_output_stream_write()
with a count of 8192, and it there happens to be 4096 bytes of space in the pipe. What happens then, is that the poll() call returns POLLOUT
, because there is some space. But then the write(fd, 8192) blocks forever.
This turns out to be a well-defined behaviour of write() on pipes. See https://linux.die.net/man/7/pipe, in particular the pipe_buf part, which says:
O_NONBLOCK disabled, n > PIPE_BUF: The write is nonatomic: the data given to write(2) may be interleaved with write(2)s by other process; the write(2) blocks until n bytes have been written.
So, we have 4096 bytes space but try to write 8192, so we block until there is all 8192 space left. In our case there isn't though, because the child is blocking on stdout writing to ourself which we will never get to, because we're blocking in write().