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 211820 a6b5b538815561ac3acdb37a3575a64e35c2ee8f
parent 211819 26b95471c5f8f41dfcb207c9358ae70d0f7ad434
child 211821 6e2c2a52ae8d14f682e4d3c55d327b03ee3e9d65
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs914563
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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)