Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • G GLib
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 862
    • Issues 862
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 40
    • Merge requests 40
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOMEGNOME
  • GLib
  • Issues
  • #2182
Closed
Open
Issue created Aug 13, 2020 by Alexander Larsson@alexlMaintainer

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().

Assignee
Assign to
Time tracking