Bug 914563 - Hack up mach to work with multiprocessing on Windows; r=glandium
authorMike Shal <mshal@mozilla.com>
Fri, 20 Jun 2014 11:35:25 -0400
changeset 189908 a6b5b538815561ac3acdb37a3575a64e35c2ee8f
parent 189907 26b95471c5f8f41dfcb207c9358ae70d0f7ad434
child 189909 6e2c2a52ae8d14f682e4d3c55d327b03ee3e9d65
push id7399
push userryanvm@gmail.com
push dateMon, 23 Jun 2014 14:59:50 +0000
treeherderfx-team@007a3b5039a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs914563
milestone33.0a1
Bug 914563 - Hack up mach to work with multiprocessing on Windows; r=glandium
mach
--- a/mach
+++ b/mach
@@ -53,9 +53,56 @@ def main(args):
             mach = load_mach(dir_path)
             sys.exit(mach.run(args[1:]))
 
     print('Could not run mach: No mach source directory found.')
     sys.exit(1)
 
 
 if __name__ == '__main__':
+    if sys.platform == 'win32':
+        # This is a complete hack to work around the fact that Windows
+        # multiprocessing needs to import the original module (ie: this
+        # file), but only works if it has a .py extension.
+	#
+	# We do this by a sort of two-level function interposing. The first
+	# level interposes forking.get_command_line() with our version defined
+	# in my_get_command_line(). Our version of get_command_line will
+	# replace the command string with the contents of the fork_interpose()
+	# function to be used in the subprocess.
+	#
+	# The subprocess then gets an interposed imp.find_module(), which we
+	# hack up to find 'mach' without the .py extension, since we already
+	# know where it is (it's us!). If we're not looking for 'mach', then
+	# the original find_module will suffice.
+        #
+        # See also: http://bugs.python.org/issue19946
+        # And: https://bugzilla.mozilla.org/show_bug.cgi?id=914563
+        import inspect
+        from multiprocessing import forking
+        global orig_command_line
+
+        def fork_interpose():
+            import imp
+            import os
+            orig_find_module = imp.find_module
+            def my_find_module(name, dirs):
+                if name == 'mach':
+                    path = os.path.join(dirs[0], 'mach')
+                    f = open(path)
+                    return (f, path, ('', 'r', imp.PY_SOURCE))
+                return orig_find_module(name, dirs)
+
+            imp.find_module = my_find_module
+            from multiprocessing.forking import main; main()
+
+        def my_get_command_line():
+            fork_code, lineno = inspect.getsourcelines(fork_interpose)
+            # Remove the first line (for 'def fork_interpose():') and the three
+	    # levels of indentation (12 spaces).
+            fork_string = ''.join(x[12:] for x in fork_code[1:])
+            cmdline = orig_command_line()
+            cmdline[2] = fork_string
+            return cmdline
+        orig_command_line = forking.get_command_line
+        forking.get_command_line = my_get_command_line
+
     main(sys.argv)