Skip to content

Read from pty master in nonblocking mode (due to unlikely deadlock) #4780

@egmontkob

Description

@egmontkob

Is there an existing issue for this?

  • I have searched the existing issues

Midnight Commander version and build configuration

4.8.33-353-g32b7a14c4

Operating system

any

Is this issue reproducible using the latest version of Midnight Commander?

  • I confirm the issue is still reproducible with the latest version of Midnight Commander

How to reproduce

src/subshell/common.c contains the following typical pattern 3 times (#4625 is about to add 2 more):

  • select() on mc_global.tty.subshell_pty, possibly along with other fds
  • if other fds were present then check if mc_global.tty.subshell_pty is said to contain data
  • read() from this fd

With tty lines, this standard pattern of reading can cause a lockup. That's because the slave side can perform a tcflush(), i.e. revoke the data already placed in the tty line. And this could happen between the select() and the blocking read() steps.

We should set the master fd to O_NONBLOCK (a.k.a. O_NDELAY) mode. Either for the duration of the read()s only, or once and for all but then make sure to adjust the write() / write_all() calls to expect that attempting to write to a clogged channel behaves differently and returns immediately (write_all() would need to be a select()+write() loop rather than just a write() loop).

I guess a helper read_nonblock() method flipping the flag back and forth is the easiest solution for now, until proper glib mainloop-based approach is implemented.

Linux has preadv2() that allows to pass flags on a per-call basis (for some reason it uses RWF_NOWAIT instead of O_NONBLOCK) but it's super non-portable.

Expected behavior

never to block

Actual behavior

super unlikely to block

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues not related to a specific subsystemprio: mediumHas the potential to affect progress

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions