提交 80ebe9c3 authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Fix usage of Popen.wait(). This is liable to deadlock if used with…

Fix usage of Popen.wait(). This is liable to deadlock if used with subprocess.PIPE and it was used like that all over the place. I've created new wrapper that will hopefully avoid this broken usage.
上级 19c0dbcb
......@@ -117,19 +117,10 @@ AddConfigVar('mode',
enum = EnumStr("g++", "")
# Test whether or not g++ is present: disable C code if it is not.
# Using the dummy file descriptor below is a workaround for a crash experienced
# in an unusual Python 2.4.4 Windows environment with the default stdin=None.
dummy_stdin = open(os.devnull)
try:
try:
rc = call_subprocess_Popen(['g++', '-v'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=dummy_stdin).wait()
except OSError:
rc = call_subprocess_Popen(['g++', '-v'])
except OSError:
rc = 1
finally:
dummy_stdin.close()
del dummy_stdin
if rc == 0:
# Keep the default linker the same as the one for the mode FAST_RUN
AddConfigVar('linker',
......
......@@ -29,7 +29,8 @@ from theano.compat.six import b, BytesIO, StringIO
from theano.gof.utils import flatten
from theano.configparser import config
from theano.gof.cc import hash_from_code
from theano.misc.windows import call_subprocess_Popen
from theano.misc.windows import (subprocess_Popen, call_subprocess_Popen,
output_subprocess_Popen)
# we will abuse the lockfile mechanism when reading and writing the registry
from theano.gof import compilelock
......@@ -1516,11 +1517,8 @@ def gcc_llvm():
pass
p = None
try:
p = call_subprocess_Popen(['g++', '--version'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.wait()
output = p.stdout.read() + p.stderr.read()
p_out = output_subprocess_Popen(['g++', '--version'])
output = p_out[0] + p_out[1]
except OSError:
# Typically means g++ cannot be found.
# So it is not an llvm compiler.
......@@ -1573,7 +1571,7 @@ class GCC_compiler(object):
GCC_compiler.march_flags = []
def get_lines(cmd, parse=True):
p = call_subprocess_Popen(cmd,
p = subprocess_Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
......@@ -1815,21 +1813,15 @@ class GCC_compiler(object):
os.write(fd, src_code)
os.close(fd)
fd = None
proc = call_subprocess_Popen(
['g++', path, '-o', exe_path] + flags,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.wait()
if proc.returncode != 0:
p_ret = call_subprocess_Popen(
['g++', path, '-o', exe_path] + flags)
if p_ret != 0:
compilation_ok = False
elif try_run:
# Try to execute the program
try:
proc = call_subprocess_Popen([exe_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.wait()
run_ok = (proc.returncode == 0)
p_ret = call_subprocess_Popen([exe_path])
run_ok = (p_ret == 0)
finally:
os.remove(exe_path)
finally:
......@@ -1962,14 +1954,14 @@ class GCC_compiler(object):
print >> sys.stderr, ' '.join(cmd)
try:
p = call_subprocess_Popen(cmd, stderr=subprocess.PIPE)
compile_stderr = decode(p.communicate()[1])
p_out = output_subprocess_Popen(cmd)
compile_stderr = decode(p_out[1])
except Exception:
# An exception can occur e.g. if `g++` is not found.
print_command_line_error()
raise
status = p.returncode
status = p_out[2]
if status:
print '==============================='
......
......@@ -16,27 +16,17 @@ import numpy
import theano
from theano.configparser import config, AddConfigVar, ConfigParam, StrParam
from theano.gof.utils import flatten
from theano.misc.windows import call_subprocess_Popen
from theano.misc.windows import output_subprocess_Popen
_logger = logging.getLogger("theano.gof.compiledir")
# Using the dummy file descriptors below is a workaround for a crash
# experienced in an unusual Python 2.4.4 Windows environment with the default
# None values.
dummy_err = open(os.devnull, 'w')
p = None
try:
p = call_subprocess_Popen(['g++', '-dumpversion'],
stdout=subprocess.PIPE,
stderr=dummy_err.fileno())
p.wait()
gcc_version_str = p.stdout.readline().strip().decode()
p_out = output_subprocess_Popen(['g++', '-dumpversion'])
gcc_version_str = p_out[0].strip().decode()
except OSError:
# Typically means gcc cannot be found.
gcc_version_str = 'GCC_NOT_FOUND'
del p
del dummy_err
def local_bitwidth():
......
......@@ -2,7 +2,7 @@ import os
import subprocess
def call_subprocess_Popen(command, **params):
def subprocess_Popen(command, **params):
"""
Utility function to work around windows behavior that open windows
"""
......@@ -36,3 +36,30 @@ def call_subprocess_Popen(command, **params):
if stdin is not None:
del stdin
return proc
def call_subprocess_Popen(command, **params):
if 'stdout' in params or 'stderr' in params:
raise TypeError("don't use stderr or stdout with call_subprocess_Popen")
null = open(os.devnull, 'wb')
# stdin to devnull is a workaround for a crash in a weird Windows
# environement where sys.stdin was None
params.setdefault('stdin', null)
params['stdout'] = null
params['stderr'] = null
p = subprocess_Popen(command, **params)
p.wait()
return p.returncode
def output_subprocess_Popen(command, **params):
if 'stdout' in params or 'stderr' in params:
raise TypeError("don't use stderr or stdout with output_subprocess_Popen")
# stdin to devnull is a workaround for a crash in a weird Windows
# environement where sys.stdin was None
if not hasattr(params, 'stdin'):
null = open(os.devnull, 'wb')
params['stdin'] = null
params['stdout'] = subprocess.PIPE
params['stderr'] = subprocess.PIPE
p = subprocess_Popen(command, **params)
out = p.communicate()
return out + (p.returncode,)
......@@ -16,7 +16,7 @@ from theano.gof.cmodule import (std_libs, std_lib_dirs,
std_include_dirs, dlimport,
get_lib_extension)
from theano.gof.python25 import any
from theano.misc.windows import call_subprocess_Popen
from theano.misc.windows import output_subprocess_Popen
_logger = logging.getLogger("theano.sandbox.cuda.nvcc_compiler")
_logger.setLevel(logging.WARN)
......@@ -98,12 +98,8 @@ nvcc_version = None
def is_nvcc_available():
"""Return True iff the nvcc compiler is found."""
def set_version():
p = call_subprocess_Popen([nvcc_path, '--version'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.wait()
ver_line = decode(p.stdout.readlines()[-1])
p_out = output_subprocess_Popen([nvcc_path, '--version'])
ver_line = decode(p_out[0].split('\n')[-1])
build, version = ver_line.split(',')[1].strip().split()
assert build == 'release'
......
......@@ -62,7 +62,7 @@ import sys
import time
import theano
from theano.misc.windows import call_subprocess_Popen
from theano.misc.windows import output_subprocess_Popen
def main(stdout=None, stderr=None, argv=None, theano_nose=None,
......@@ -271,19 +271,17 @@ def run(stdout, stderr, argv, theano_nose, batch_size, time_profile,
time.ctime(), test_id, data["ids"][test_id]))
f_rawlog.flush()
proc = call_subprocess_Popen(
p_out = output_subprocess_Popen(
([python, theano_nose, '-v', '--with-id']
+ [str(test_id)] + argv +
['--disabdocstring']),
['--disabdocstring']))
# the previous option calls a custom Nosetests plugin
# precluding automatic sustitution of doc. string for
# test name in display
# (see class 'DisabDocString' in file theano-nose)
stderr=subprocess.PIPE,
stdout=dummy_out.fileno())
# recovering and processing data from pipe
err = proc.stderr.read()
err = p_out[1]
# print the raw log
f_rawlog.write(err)
f_rawlog.flush()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论