forked from M-Labs/artiq
compiler: do not pass files to external tools while they are opened.
This fixes access violations on Windows that are present both with input and output files. For some reason, Cygwin-compiled binutils did not exhibit this problem, but MSYS-compiled binutils do. Fixes #961.
This commit is contained in:
parent
5cb2602021
commit
4b5a78e231
|
@ -1,4 +1,4 @@
|
||||||
import os, sys, tempfile, subprocess
|
import os, sys, tempfile, subprocess, io
|
||||||
from artiq.compiler import types
|
from artiq.compiler import types
|
||||||
from llvmlite_artiq import ir as ll, binding as llvm
|
from llvmlite_artiq import ir as ll, binding as llvm
|
||||||
|
|
||||||
|
@ -8,27 +8,25 @@ llvm.initialize_all_asmprinters()
|
||||||
|
|
||||||
class RunTool:
|
class RunTool:
|
||||||
def __init__(self, pattern, **tempdata):
|
def __init__(self, pattern, **tempdata):
|
||||||
self.files = []
|
self._pattern = pattern
|
||||||
self.pattern = pattern
|
self._tempdata = tempdata
|
||||||
self.tempdata = tempdata
|
self._tempnames = {}
|
||||||
|
self._tempfiles = {}
|
||||||
def maketemp(self, data):
|
|
||||||
f = tempfile.NamedTemporaryFile()
|
|
||||||
f.write(data)
|
|
||||||
f.flush()
|
|
||||||
self.files.append(f)
|
|
||||||
return f
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
tempfiles = {}
|
for key, data in self._tempdata.items():
|
||||||
tempnames = {}
|
if data is None:
|
||||||
for key in self.tempdata:
|
fd, filename = tempfile.mkstemp()
|
||||||
tempfiles[key] = self.maketemp(self.tempdata[key])
|
os.close(fd)
|
||||||
tempnames[key] = tempfiles[key].name
|
self._tempnames[key] = filename
|
||||||
|
else:
|
||||||
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
|
f.write(data)
|
||||||
|
self._tempnames[key] = f.name
|
||||||
|
|
||||||
cmdline = []
|
cmdline = []
|
||||||
for argument in self.pattern:
|
for argument in self._pattern:
|
||||||
cmdline.append(argument.format(**tempnames))
|
cmdline.append(argument.format(**self._tempnames))
|
||||||
|
|
||||||
process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout, stderr = process.communicate()
|
stdout, stderr = process.communicate()
|
||||||
|
@ -36,12 +34,17 @@ class RunTool:
|
||||||
raise Exception("{} invocation failed: {}".
|
raise Exception("{} invocation failed: {}".
|
||||||
format(cmdline[0], stderr.decode('utf-8')))
|
format(cmdline[0], stderr.decode('utf-8')))
|
||||||
|
|
||||||
tempfiles["__stdout__"] = stdout.decode('utf-8')
|
self._tempfiles["__stdout__"] = io.StringIO(stdout.decode('utf-8'))
|
||||||
return tempfiles
|
for key in self._tempdata:
|
||||||
|
if self._tempdata[key] is None:
|
||||||
|
self._tempfiles[key] = open(self._tempnames[key], "rb")
|
||||||
|
return self._tempfiles
|
||||||
|
|
||||||
def __exit__(self, exc_typ, exc_value, exc_trace):
|
def __exit__(self, exc_typ, exc_value, exc_trace):
|
||||||
for f in self.files:
|
for file in self._tempfiles.values():
|
||||||
f.close()
|
file.close()
|
||||||
|
for filename in self._tempnames.values():
|
||||||
|
os.unlink(filename)
|
||||||
|
|
||||||
def _dump(target, kind, suffix, content):
|
def _dump(target, kind, suffix, content):
|
||||||
if target is not None:
|
if target is not None:
|
||||||
|
@ -166,7 +169,7 @@ class Target:
|
||||||
with RunTool([self.triple + "-ld", "-shared", "--eh-frame-hdr"] +
|
with RunTool([self.triple + "-ld", "-shared", "--eh-frame-hdr"] +
|
||||||
["{{obj{}}}".format(index) for index in range(len(objects))] +
|
["{{obj{}}}".format(index) for index in range(len(objects))] +
|
||||||
["-o", "{output}"],
|
["-o", "{output}"],
|
||||||
output=b"",
|
output=None,
|
||||||
**{"obj{}".format(index): obj for index, obj in enumerate(objects)}) \
|
**{"obj{}".format(index): obj for index, obj in enumerate(objects)}) \
|
||||||
as results:
|
as results:
|
||||||
library = results["output"].read()
|
library = results["output"].read()
|
||||||
|
@ -181,7 +184,7 @@ class Target:
|
||||||
|
|
||||||
def strip(self, library):
|
def strip(self, library):
|
||||||
with RunTool([self.triple + "-strip", "--strip-debug", "{library}", "-o", "{output}"],
|
with RunTool([self.triple + "-strip", "--strip-debug", "{library}", "-o", "{output}"],
|
||||||
library=library, output=b"") \
|
library=library, output=None) \
|
||||||
as results:
|
as results:
|
||||||
return results["output"].read()
|
return results["output"].read()
|
||||||
|
|
||||||
|
@ -198,7 +201,7 @@ class Target:
|
||||||
"--demangle", "--exe={library}"] + offset_addresses,
|
"--demangle", "--exe={library}"] + offset_addresses,
|
||||||
library=library) \
|
library=library) \
|
||||||
as results:
|
as results:
|
||||||
lines = iter(results["__stdout__"].rstrip().split("\n"))
|
lines = iter(results["__stdout__"].read().rstrip().split("\n"))
|
||||||
backtrace = []
|
backtrace = []
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -226,7 +229,7 @@ class Target:
|
||||||
|
|
||||||
def demangle(self, names):
|
def demangle(self, names):
|
||||||
with RunTool([self.triple + "-c++filt"] + names) as results:
|
with RunTool([self.triple + "-c++filt"] + names) as results:
|
||||||
return results["__stdout__"].rstrip().split("\n")
|
return results["__stdout__"].read().rstrip().split("\n")
|
||||||
|
|
||||||
class NativeTarget(Target):
|
class NativeTarget(Target):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
Loading…
Reference in New Issue