Bug 989048 - Clean up emulator temporary files and do not overwrite userdata image. r=ahal, a=test-only
authorTing-Yu Chou <janus926@gmail.com>
Fri, 23 Jan 2015 21:55:43 +0800
changeset 243029 89ea80802586
parent 243028 d340f3d3439d
child 243030 775b46e5b648
push id4368
push userryanvm@gmail.com
push date2015-01-26 15:37 +0000
treeherdermozilla-beta@e6cefc687439 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal, test-only
bugs989048
milestone36.0
Bug 989048 - Clean up emulator temporary files and do not overwrite userdata image. r=ahal, a=test-only
testing/mozbase/mozrunner/mozrunner/devices/emulator.py
--- a/testing/mozbase/mozrunner/mozrunner/devices/emulator.py
+++ b/testing/mozbase/mozrunner/mozrunner/devices/emulator.py
@@ -46,38 +46,39 @@ class Emulator(Device):
     telnet = None
 
     def __init__(self, app_ctx, arch, resolution=None, sdcard=None, userdata=None,
                  no_window=None, binary=None, **kwargs):
         Device.__init__(self, app_ctx, **kwargs)
 
         self.arch = ArchContext(arch, self.app_ctx, binary=binary)
         self.resolution = resolution or '320x480'
+        self.tmpdir = tempfile.mkdtemp()
         self.sdcard = None
         if sdcard:
             self.sdcard = self.create_sdcard(sdcard)
-        self.userdata = os.path.join(self.arch.sysdir, 'userdata.img')
-        if userdata:
-            self.userdata = tempfile.NamedTemporaryFile(prefix='qemu-userdata')
-            shutil.copyfile(userdata, self.userdata)
+        self.userdata = tempfile.NamedTemporaryFile(prefix='userdata-qemu', dir=self.tmpdir)
+        self.initdata = userdata if userdata else os.path.join(self.arch.sysdir, 'userdata.img')
         self.no_window = no_window
 
         self.battery = EmulatorBattery(self)
         self.geo = EmulatorGeo(self)
         self.screen = EmulatorScreen(self)
 
     @property
     def args(self):
         """
         Arguments to pass into the emulator binary.
         """
         qemu_args = [self.arch.binary,
                      '-kernel', self.arch.kernel,
                      '-sysdir', self.arch.sysdir,
-                     '-data', self.userdata]
+                     '-data', self.userdata.name,
+                     '-initdata', self.initdata,
+                     '-wipe-data']
         if self.no_window:
             qemu_args.append('-no-window')
         if self.sdcard:
             qemu_args.extend(['-sdcard', self.sdcard])
         qemu_args.extend(['-memory', '512',
                           '-partition-size', '512',
                           '-verbose',
                           '-skin', self.resolution,
@@ -89,16 +90,21 @@ class Emulator(Device):
         """
         Starts a new emulator.
         """
         if self.proc:
             return
 
         original_devices = set(self._get_online_devices())
 
+        # QEMU relies on atexit() to remove temporary files, which does not
+        # work since mozprocess uses SIGKILL to kill the emulator process.
+        # Use a customized temporary directory so we can clean it up.
+        os.environ['ANDROID_TMP'] = self.tmpdir
+
         qemu_log = None
         qemu_proc_args = {}
         if self.logdir:
             # save output from qemu to logfile
             qemu_log = os.path.join(self.logdir, 'qemu.log')
             if os.path.isfile(qemu_log):
                 self._rotate_log(qemu_log)
             qemu_proc_args['logfile'] = qemu_log
@@ -140,17 +146,17 @@ class Emulator(Device):
 
     def create_sdcard(self, sdcard_size):
         """
         Creates an sdcard partition in the emulator.
 
         :param sdcard_size: Size of partition to create, e.g '10MB'.
         """
         mksdcard = self.app_ctx.which('mksdcard')
-        path = tempfile.mktemp(prefix='sdcard')
+        path = tempfile.mktemp(prefix='sdcard', dir=self.tmpdir)
         sdargs = [mksdcard, '-l', 'mySdCard', sdcard_size, path]
         sd = subprocess.Popen(sdargs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
         retcode = sd.wait()
         if retcode:
             raise Exception('unable to create sdcard: exit code %d: %s'
                             % (retcode, sd.stdout.read()))
         return path
 
@@ -158,19 +164,19 @@ class Emulator(Device):
         """
         Cleans up and kills the emulator.
         """
         Device.cleanup(self)
         if self.proc:
             self.proc.kill()
             self.proc = None
 
-        # Remove temporary sdcard
-        if self.sdcard and os.path.isfile(self.sdcard):
-            os.remove(self.sdcard)
+        # Remove temporary files
+        self.userdata.close()
+        shutil.rmtree(self.tmpdir)
 
     # TODO this function is B2G specific and shouldn't live here
     @uses_marionette
     def wait_for_system_message(self, marionette):
         marionette.set_script_timeout(45000)
         # Telephony API's won't be available immediately upon emulator
         # boot; we have to wait for the syste-message-listener-ready
         # message before we'll be able to use them successfully.  See