diff options
author | Tom Tanner <ttanner2@bloomberg.net> | 2013-10-04 16:32:02 (GMT) |
---|---|---|
committer | Tom Tanner <ttanner2@bloomberg.net> | 2013-10-04 16:32:02 (GMT) |
commit | ae5053ffaf485d77c9ee37873169e3dd6be7b579 (patch) | |
tree | 08d0d5655f3e1fa16692780d9016b35ba2ca20b9 /src | |
parent | d83777e9c6b676c0051d120bf3405e9117a031cf (diff) | |
download | SCons-ae5053ffaf485d77c9ee37873169e3dd6be7b579.zip SCons-ae5053ffaf485d77c9ee37873169e3dd6be7b579.tar.gz SCons-ae5053ffaf485d77c9ee37873169e3dd6be7b579.tar.bz2 |
Change posix.py to use subprocess as we only support python 2.4.
Added a test for leaking handles.
Diffstat (limited to 'src')
-rw-r--r-- | src/engine/SCons/Platform/posix.py | 178 |
1 files changed, 14 insertions, 164 deletions
diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 3da1be7..2e21e5a 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -47,11 +47,6 @@ exitvalmap = { 13 : 126, } -try: - MAXFD = os.sysconf("SC_OPEN_MAX") -except: - MAXFD = 256 - def escape(arg): "escape shell special characters" slash = '\\' @@ -63,177 +58,32 @@ def escape(arg): return '"' + arg + '"' -def exec_system(l, env): - stat = os.system(' '.join(l)) - if stat & 0xff: - return stat | 0x80 - return stat >> 8 - -def exec_spawnvpe(l, env): - stat = os.spawnvpe(os.P_WAIT, l[0], l, env) - # os.spawnvpe() returns the actual exit code, not the encoding - # returned by os.waitpid() or os.system(). - return stat - -def exec_fork(l, env): - pid = os.fork() - if not pid: - # Child process. - exitval = 127 - os.closerange(3, MAXFD) - try: - os.execvpe(l[0], l, env) - except OSError, e: - exitval = exitvalmap.get(e[0], e[0]) - sys.stderr.write("scons: %s: %s\n" % (l[0], e[1])) - os._exit(exitval) - else: - # Parent process. - pid, stat = os.waitpid(pid, 0) - if stat & 0xff: - return stat | 0x80 - return stat >> 8 - -def _get_env_command(sh, escape, cmd, args, env): - s = ' '.join(args) - if env: - l = ['env', '-'] + \ - [escape(t[0])+'='+escape(t[1]) for t in env.items()] + \ - [sh, '-c', escape(s)] - s = ' '.join(l) - return s - -def env_spawn(sh, escape, cmd, args, env): - return exec_system([_get_env_command( sh, escape, cmd, args, env)], env) - -def spawnvpe_spawn(sh, escape, cmd, args, env): - return exec_spawnvpe([sh, '-c', ' '.join(args)], env) +def exec_subprocess(l, env): + proc = subprocess.Popen(l, env = env, close_fds = True) + return proc.wait() -def fork_spawn(sh, escape, cmd, args, env): - return exec_fork([sh, '-c', ' '.join(args)], env) - -def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr): - stdout_eof = stderr_eof = 0 - while not (stdout_eof and stderr_eof): - try: - (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], []) - if cmd_stdout in i: - str = cmd_stdout.read() - if len(str) == 0: - stdout_eof = 1 - elif stdout is not None: - stdout.write(str) - if cmd_stderr in i: - str = cmd_stderr.read() - if len(str) == 0: - #sys.__stderr__.write( "stderr_eof=1\n" ) - stderr_eof = 1 - else: - #sys.__stderr__.write( "str(stderr) = %s\n" % str ) - stderr.write(str) - except select.error, (_errno, _strerror): - if _errno != errno.EINTR: - raise +def subprocess_spawn(sh, escape, cmd, args, env): + return exec_subprocess([sh, '-c', ' '.join(args)], env) def exec_popen3(l, env, stdout, stderr): - proc = subprocess.Popen(' '.join(l), - stdout=stdout, - stderr=stderr, - shell=True) - stat = proc.wait() - if stat & 0xff: - return stat | 0x80 - return stat >> 8 - -def exec_piped_fork(l, env, stdout, stderr): - # spawn using fork / exec and providing a pipe for the command's - # stdout / stderr stream - if stdout != stderr: - (rFdOut, wFdOut) = os.pipe() - (rFdErr, wFdErr) = os.pipe() - else: - (rFdOut, wFdOut) = os.pipe() - rFdErr = rFdOut - wFdErr = wFdOut - # do the fork - pid = os.fork() - if not pid: - # Child process - os.close( rFdOut ) - if rFdOut != rFdErr: - os.close( rFdErr ) - os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ? - os.dup2( wFdErr, 2 ) - os.close( wFdOut ) - if stdout != stderr: - os.close( wFdErr ) - os.closerange(3, MAXFD) - exitval = 127 - try: - os.execvpe(l[0], l, env) - except OSError, e: - exitval = exitvalmap.get(e[0], e[0]) - stderr.write("scons: %s: %s\n" % (l[0], e[1])) - os._exit(exitval) - else: - # Parent process - pid, stat = os.waitpid(pid, 0) - os.close( wFdOut ) - if stdout != stderr: - os.close( wFdErr ) - childOut = os.fdopen( rFdOut ) - if stdout != stderr: - childErr = os.fdopen( rFdErr ) - else: - childErr = childOut - process_cmd_output(childOut, childErr, stdout, stderr) - os.close( rFdOut ) - if stdout != stderr: - os.close( rFdErr ) - if stat & 0xff: - return stat | 0x80 - return stat >> 8 + proc = subprocess.Popen(l, env = env, close_fds = True, + stdout = stdout, + stderr = stderr) + return proc.wait() def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr): # spawn using Popen3 combined with the env command # the command name and the command's stdout is written to stdout # the command's stderr is written to stderr - return exec_popen3([_get_env_command(sh, escape, cmd, args, env)], + return exec_popen3([sh, '-c', ' '.join(args)], env, stdout, stderr) -def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr): - # spawn using fork / exec and providing a pipe for the command's - # stdout / stderr stream - return exec_piped_fork([sh, '-c', ' '.join(args)], - env, stdout, stderr) - - def generate(env): - # If os.spawnvpe() exists, we use it to spawn commands. Otherwise - # if the env utility exists, we use os.system() to spawn commands, - # finally we fall back on os.fork()/os.exec(). - # - # os.spawnvpe() is prefered because it is the most efficient. But - # for Python versions without it, os.system() is prefered because it - # is claimed that it works better with threads (i.e. -j) and is more - # efficient than forking Python. - # - # NB: Other people on the scons-users mailing list have claimed that - # os.fork()/os.exec() works better than os.system(). There may just - # not be a default that works best for all users. - - if 'spawnvpe' in os.__dict__: - spawn = spawnvpe_spawn - elif env.Detect('env'): - spawn = env_spawn - else: - spawn = fork_spawn - - if env.Detect('env'): - pspawn = piped_env_spawn - else: - pspawn = piped_fork_spawn + # Bearing in mind we have python 2.4 as a baseline, we can just do this: + spawn = subprocess_spawn + pspawn = piped_env_spawn + # Note that this means that 'escape' is no longer used if 'ENV' not in env: env['ENV'] = {} |