badams
badams

Reputation: 108

Subprocess opened with PIPE still reading input from terminal

Python App

My Python 3.6.8 app runs on CentOS 7.6, and:

Sub-Process

Popen Command

I launch the sub-process from the main thread with this command:

launch_cmd = "{} {} {} {}".format(path_of_compiled_binary, opt1, opt2, opt3)
self.myproc = subprocess.Popen(launch_cmd.split(), shell=False,
    cwd=self.testing_dir, close_fds=True, stdin=subprocess.PIPE,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env,
    bufsize=1, universal_newlines=True, preexec_fn=self.ignore_sigint)

Write Command

I try to give the sub-process commands with

cmd = self.generate_cmd()
cmd = cmd + "\n"
bytes_sent = self.myproc.stdin.write(cmd)
self.myproc.stdin.flush()

File Descriptors

`

lr-x------. 1 demo demo 64 Jun  5 10:44 0 -> pipe:[58635]
l-wx------. 1 demo demo 64 Jun  5 10:44 1 -> pipe:[58636]
l-wx------. 1 demo demo 64 Jun  5 10:44 2 -> pipe:[58636]
lr-x------. 1 demo demo 64 Jun  5 10:44 3 -> /dev/null
lr-x------. 1 demo demo 64 Jun  5 10:44 4 -> path_of_compiled_binary
lr-x------. 1 demo demo 64 Jun  5 10:44 5 -> /dev/tty
l-wx------. 1 demo demo 64 Jun  5 10:44 6 -> /dev/tty
lrwx------. 1 demo demo 64 Jun  5 10:44 7 -> socket:[59509]
lrwx------. 1 demo demo 64 Jun  5 10:44 8 -> /dev/ttyACM0
lr-x------. 1 demo demo 64 Jun  5 10:44 9 -> /tmp/par-64656d6f/temp-15579/inc/lib/PDL/IO/Pic.pm

Upvotes: 0

Views: 451

Answers (1)

badams
badams

Reputation: 108

Sub-process reading from tty, not stdin

The sub-process opens 2 file descriptors to /dev/tty:

lr-x------. 1 demo demo 64 Jun  5 10:44 5 -> /dev/tty
l-wx------. 1 demo demo 64 Jun  5 10:44 6 -> /dev/tty
  • @that-other-guy suggested that the sub-process reads from one of these instead of stdin.
  • Apparently 5, since its mode is read only?

/usr/bin/script utility

Another suggestion from @that-other-guy:

  • Use script to launch the sub-process.
  • The script utility is designed to capture a shell session into a live transcript.
  • The -c option spawns any given command instead of a shell.
  • Providing /dev/null for the file argument says to forget the transcript.

Re-coding with script:

launch_cmd = "{} {} {} {}".format(path_of_compiled_binary, opt1, opt2, opt3)
script_argv = ["/usr/bin/script", "-c", launch_cmd, "/dev/null"]
self.myproc = subprocess.Popen(script_argv, shell=False,
    cwd=self.testing_dir, close_fds=True, stdin=subprocess.PIPE,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env,
    bufsize=1, universal_newlines=True, preexec_fn=self.ignore_sigint)

How it works

  • script spawns the sub-process and interacts with it in a pseudoterminal.
  • script reads stdin from the pipe and echoes it into its pseudoterminal for the sub-process to read.
  • Now it doesn't matter if the sub-process is reading the terminal on 5 instead of stdin on 0.

This change overcame the problem. The sub-process now receives commands from the app.

Upvotes: 1

Related Questions