Shrikanth Kalluraya
Shrikanth Kalluraya

Reputation: 1119

Not able to give inputs to subprocess(process which runs adb shell command) after 100 iterations

I want to run a stress test for adb(android debug bridge) shell. ( adb shell in this respect just a command line tool provided by Android phones).

I create a sub-process from python and in this subprocess i execute 'adb shell' command. there are some commands which has to be given to this subprocess which I am providing via stdin proper of the sub process.

Everything seems to be fine but when I am running a stress test. after around 100 iterations the command which I give to stdin does not reach to subprocess. If I run commands in separate terminal it is running fine. but the problem is with this stdin.

Can anyone tell me what I am doing wrong. Below is the code sample

class ADB():
def __init__(self):
    self.proc = subprocess.Popen('adb shell', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True,bufsize=0)


def provideAMcommand(self, testParam):
    try:
        cmd1 = "am startservice -n com.test.myapp/.ADBSupport -e \"" + "command" + "\" \"" + "test" + "\""  
        cmd2 = " -e \"" + "param" + "\"" + " " + testParam
        print cmd1+cmd2
        sys.stdout.flush()
        self.proc.stdin.write(cmd1 + cmd2 + "\n")
    except:
        raise Exception("Phone is not Connected to Desktop or ADB is not available \n")

Upvotes: 0

Views: 2138

Answers (2)

jfs
jfs

Reputation: 414585

If it works for the first few commands but blocks later then you might forgot to read from self.proc.stdout that might lead to (as the docs warn) to OS pipe buffer filling up and blocking the child process.

To discard the output, redirect it to os.devnull:

import os
from subprocess import Popen, PIPE, STDOUT

DEVNULL = open(os.devnull, 'wb')
# ...
self.proc = Popen(['adb', 'shell'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
# ...
self.proc.stdin.write(cmd1 + cmd2 + "\n")
self.proc.stdin.flush()

There is pexpect module that might be a better tool for a dialog-based interaction (if you want both read/write intermitently).

Upvotes: 1

Troels Folke
Troels Folke

Reputation: 927

IN provideAMcommand you are writing to and flushing the stdout of your main process. That will not send anything to the stdin of the child process you have created with Popen. The following code creates a new bash child process, a bit like the code in your __init__:

import subprocess as sp
cproc = sp.Popen("bash", stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)

Now, the easiest way to communicate with that child process is the following:

#Send command 'ls' to bash.
out, err = cproc.communicate("ls")

This will send the text "ls" and EOF to bash (equal to running a bash script with only the text "ls" in it). Bash will execute the ls command and then quit. Anything that bash or ls write to stdout and stderr will end up in the variables out and err respectively. I have not used the adb shell, but I guess it behaves like bash in this regard.

If you just want your child process to print to the terminal, don't specify the stdout and stderr arguments to Popen.

You can check the exit code of the child, and raise an exception if it is non-zero (indicating an error):

if (cproc.returncode != 0):
     raise Exception("Child process returned non-zero exit code")

Upvotes: 0

Related Questions