task: calculate correct cmdline bytes

The previous patches to workaround
http://support.microsoft.com/kb/830473 drastically over estimated the
number of characters in commands by treating the repr() version of the
command array as a reasonable estimator of commandline length. This
caused commands attempt to write argsfiles before they should have.

The new calculation calculates the number characters in the command
array and adds the number of spaces that would be added by ' '.join(cmd)
this provides a much closer estimate of the commandline length.

This also limits the CLI-length on non windows platforms to 200kB. This
prevents us hitting the much larger argument limits on Linux/BSD/MacOS
platforms.
This commit is contained in:
James Harris 2019-02-15 10:50:27 -06:00
parent f01354049d
commit 4046e48ac1
1 changed files with 22 additions and 16 deletions

View File

@ -308,23 +308,29 @@ class Task(evil):
# workaround for command line length limit:
# http://support.microsoft.com/kb/830473
if not isinstance(cmd, str) and (len(repr(cmd)) >= 8192 if Utils.is_win32 else len(cmd) > 200000):
cmd, args = self.split_argfile(cmd)
try:
(fd, tmp) = tempfile.mkstemp()
os.write(fd, '\r\n'.join(args).encode())
os.close(fd)
if Logs.verbose:
Logs.debug('argfile: @%r -> %r', tmp, args)
return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw)
finally:
if not isinstance(cmd, str):
# Calculate commandline length:
cmd_bytes = sum([len(arg) for arg in cmd] + len(cmd) -1)
# Shunt arguments to a temporary file if the command is
# going to be too long.
if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000):
cmd, args = self.split_argfile(cmd)
try:
os.remove(tmp)
except OSError:
# anti-virus and indexers can keep files open -_-
pass
else:
return self.generator.bld.exec_command(cmd, **kw)
(fd, tmp) = tempfile.mkstemp()
os.write(fd, '\r\n'.join(args).encode())
os.close(fd)
if Logs.verbose:
Logs.debug('argfile: @%r -> %r', tmp, args)
return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw)
finally:
try:
os.remove(tmp)
except OSError:
# anti-virus and indexers can keep files open -_-
pass
# If this line is hit then the command can be passed down stream
# directly.
return self.generator.bld.exec_command(cmd, **kw)
def process(self):
"""