0

I am using MonkeyRunner for Android Automation Testing on a real device and run overnight tests. During one of those extensive automated tests I have discovered that whenever MonkeyRunner takes a screenshot, a zombie process is created on the devices internal system. Here you can see below the zombie processes when I run adb shell ps command:

enter image description here

As the zombie processes increase, the device becomes unresponsive and it starts hanging up. In MonkeyRunner, taking screenshot is the only way of verification. Thus, this issue is highly critical when running extensive tests that take many hours.

I have also seen this that says

The framebuffer_service is not doing a "wait" for the spawned screencap process to complete. Consequently, the child processes become zombie processes.

and suggests modifying the adb source code itself. However, I think there must be any other solution without going deep down to the source code.

Any ideas / suggestions how to solve this issue?

gbudan
  • 889
  • 7
  • 17
  • monkeyrunner unreliability when running long duration tests was one of the main reasons I started **[AndroidViewClient/culebra](https://github.com/dtmilano/AndroidViewClient)**. Give it a try. – Diego Torres Milano May 13 '14 at 14:24
  • Was thinking giving culebra a go today indeed. It is really frustrating to encounter such a simple but also a critical issue. – gbudan May 13 '14 at 15:55
  • Can you change the code on the development machine side to run something custom on the device (instead or as an intermediary), which does wait for the child? – Chris Stratton May 14 '14 at 16:57

1 Answers1

1

I've seen that depends very much on the android version and screencap implementation. You can run this test (which succeeds on KitKat but may fail on previous versions) to verify your case.

#! /usr/bin/python -u
# -*- coding: utf-8 -*-
'''
Copyright (C) 2014  Diego Torres Milano
'''

import sys
import unittest

from com.dtmilano.android.adb.adbclient import AdbClient

VERBOSE = True
TIMES = 40
SLEEP = 0

def repeat(times):
    def repeater(t):
        def caller(*args):
            for f in (t,)*times:
                if VERBOSE:
                    sys.stdout.write('.')
                f(*args)
                if SLEEP:
                    time.sleep(SLEEP)
        return caller
    return repeater

class TakeSnapshotTests(unittest.TestCase):

    def setUp(self):
        self.device = AdbClient(serialno=serialno)

    def tearDown(self):
        pass

    @repeat(TIMES)
    def testSnapshot(self):
        self.device.takeSnapshot(reconnect=True).save('/dev/null', 'PNG')
        out = self.device.shell('ps | grep screencap').split('\n')
        if len(out) > 1:
            self.fail(out)

    @staticmethod
    def main():
        unittest.main()

if __name__ == '__main__':
    if len(sys.argv) >= 2:
        serialno = sys.argv.pop(1)
    else:
        serialno = '.*'
    TakeSnapshotTests.main()
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • Thanks for the test case. Unfortunately, it failed in my case. It seems like i just have to accept it as it is and try to make use of **AndroidViewClient** as much as possible. – gbudan May 20 '14 at 16:00