Why is my python script that runs the adb shell monkey command crashing for large values of events?
Question: I have written a small python function that runs an adb shell monkey -p -v
command along with an adb logcat command using subprocess.popen. For values
larger than 100, this program crashes and I'm not sure why.

here is monkey_runner.py

    
    
    import os, subprocess
    def run_monkey_process(package, num_commands):
            monkeycmd = "adb shell monkey -p " + package + " -v " + num_commands
            monkeyprocess = subprocess.Popen(monkeycmd, stdout=subprocess.PIPE)
            logcatcmd = "adb logcat"
            logcatprocess = subprocess.Popen(logcatcmd, stdout=subprocess.PIPE)
            monkeystring = monkeyprocess.communicate(input=None)[0]
            logcatstring = logcatprocess.communicate(input=None)[0]
            monkeyreturncode = monkeyprocess.poll()
            logcatreturncode = logcatprocess.poll()
    
    
            if(monkeyreturncode >=0):
                    monkeyprocess.kill()
                    logcatprocess.kill()
    
                    return monkeystring, logcatstring
    
            else:
                    print 'command failure'
                    return 'you', 'fail'
    

I can put my gui code here too, but it's nothing special.

Here is the stacktrace

    
    
    Exception in Tkinter callback
    Traceback (most recent call last):
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
        return self.func(*args)
      File "C:\Users\brandon.dalesandro\Desktop\Zonar\mankey\monkey_runner_gui.py", line 25, in goCallBack
        returned = run_monkey_process(package, num)
      File "C:\Users\brandon.dalesandro\Desktop\Zonar\mankey\monkey_runner.py", line 8, in run_monkey_process
        logcatstring = logcatprocess.communicate(input=None)[0]
      File "C:\Python27\lib\subprocess.py", line 798, in communicate
        stdout = _eintr_retry_call(self.stdout.read)
      File "C:\Python27\lib\subprocess.py", line 478, in _eintr_retry_call
        return func(*args)
    KeyboardInterrupt
    


Answer: This _might_ be your problem, but it's hard to tell without more information…

You've given the subprocess a pipe, but you don't read from it until after
it's finished. The
[warning](http://docs.python.org/2/library/subprocess.html#subprocess.Popen.poll)
in the docs explains why this is bad:

> This will deadlock when using `stdout=PIPE` and/or `stderr=PIPE` and the
> child process generates enough output to a pipe such that it blocks waiting
> for the OS pipe buffer to accept more data. Use `communicate()` to avoid
> that.

It makes perfect sense that it would work for small numbers of commands—when
there's not enough data to fill the pipe buffer—but hang for larger numbers.

Looping around `poll` instead of calling `wait` doesn't help anything; all it
does is burn 100% CPU for no reason. You're still not reading from the pipe.

And calling `communicate` after the process has finished doesn't help either.
If the pipe has filled up, the subprocess will be blocked forever, `poll` will
never return a value, and you won't ever even get to `communicate`.

And since `communicate` already does its own `wait`, it's really all you need:

    
    
    monkeyprocess = subprocess.Popen(monkeycmd, stdout=subprocess.PIPE, bufsize=1)
    monkeystring = monkeyprocess.communicate(input=None)[0]
    returncode = monkeyprocess.returncode
    

