aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/shared.py98
1 files changed, 50 insertions, 48 deletions
diff --git a/tools/shared.py b/tools/shared.py
index 9f170a58..19ba71bb 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -2,61 +2,63 @@ import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess
from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp
-# A helper class that is used on Windows to represent the subprocess object that is the return value of Popen.
-class MockPopen:
- def __init__(self, stdout, stderr, returncode):
- self.returncode = returncode
- self.output = (stdout, stderr)
- def communicate(self):
- return self.output
- def poll(self):
- return self.returncode
- def kill(self):
- return # We've already communicate()d the process (waited for its completion), so can't kill() anymore. Therefore this is a no-op.
-
# On Windows python suffers from a particularly nasty bug if python is spawning new processes while python itself is spawned from some other non-console process.
# Use a custom replacement for Popen on Windows to avoid the "WindowsError: [Error 6] The handle is invalid" errors when emcc is driven through cmake or mingw32-make.
# See http://bugs.python.org/issue3905
-def call_process(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False,
- shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0):
- # (stdin, stdout, stderr) store what the caller originally wanted to be done with the streams.
- # (stdin_, stdout_, stderr_) will store the fixed set of streams that workaround the bug.
- stdin_ = stdin
- stdout_ = stdout
- stderr_ = stderr
-
- # If the caller wants one of these PIPEd, we must PIPE them all to avoid the 'handle is invalid' bug.
- if stdin_ == PIPE or stdout_ == PIPE or stderr_ == PIPE:
- if stdin_ == None:
- stdin_ = PIPE
- if stdout_ == None:
- stdout_ = PIPE
- if stderr_ == None:
- stderr_ = PIPE
-
- # Call the process with fixed streams.
- process = subprocess.Popen(args, bufsize, executable, stdin_, stdout_, stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
- output = process.communicate()
-
- # If caller never wanted to PIPE stdout or stderr, route the output back to screen to avoid swallowing output.
- if stdout == None and stdout_ == PIPE and len(output[0].strip()) > 0:
- print >> sys.stdout, output[0]
- if stderr == None and stderr_ == PIPE and len(output[1].strip()) > 0:
- print >> sys.stderr, output[1]
+class WindowsPopen:
+ def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False,
+ shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0):
+ self.stdin = stdin
+ self.stdout = stdout
+ self.stderr = stderr
+
+ # (stdin, stdout, stderr) store what the caller originally wanted to be done with the streams.
+ # (stdin_, stdout_, stderr_) will store the fixed set of streams that workaround the bug.
+ self.stdin_ = stdin
+ self.stdout_ = stdout
+ self.stderr_ = stderr
+
+ # If the caller wants one of these PIPEd, we must PIPE them all to avoid the 'handle is invalid' bug.
+ if self.stdin_ == PIPE or self.stdout_ == PIPE or self.stderr_ == PIPE:
+ if self.stdin_ == None:
+ self.stdin_ = PIPE
+ if self.stdout_ == None:
+ self.stdout_ = PIPE
+ if self.stderr_ == None:
+ self.stderr_ = PIPE
- # Return a mock object to the caller. This works as long as all emscripten code immediately .communicate()s the result, and doesn't
- # leave the process object around for longer/more exotic uses.
- if stdout == None and stderr == None:
- return MockPopen(None, None, process.returncode)
- if stdout == None:
- return MockPopen(None, output[1], process.returncode)
- if stderr == None:
- return MockPopen(output[0], None, process.returncode)
- return MockPopen(output[0], output[1], process.returncode)
+ # Call the process with fixed streams.
+ self.process = subprocess.Popen(args, bufsize, executable, self.stdin_, self.stdout_, self.stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
+
+ def communicate(self, input=None):
+ output = self.process.communicate(input)
+ self.returncode = self.process.returncode
+
+ # If caller never wanted to PIPE stdout or stderr, route the output back to screen to avoid swallowing output.
+ if self.stdout == None and self.stdout_ == PIPE and len(output[0].strip()) > 0:
+ print >> sys.stdout, output[0]
+ if self.stderr == None and self.stderr_ == PIPE and len(output[1].strip()) > 0:
+ print >> sys.stderr, output[1]
+
+ # Return a mock object to the caller. This works as long as all emscripten code immediately .communicate()s the result, and doesn't
+ # leave the process object around for longer/more exotic uses.
+ if self.stdout == None and self.stderr == None:
+ return (None, None)
+ if self.stdout == None:
+ return (None, output[1])
+ if self.stderr == None:
+ return (output[0], None)
+ return (output[0], output[1])
+
+ def poll(self):
+ return self.process.returncode
+
+ def kill(self):
+ return self.process.kill
# Install our replacement Popen handler if we are running on Windows to avoid python spawn process function.
if os.name == 'nt':
- Popen = call_process
+ Popen = WindowsPopen
import js_optimizer