# HG changeset patch # User Daniel Dourvaris # Date 2019-11-15 23:51:57 # Node ID 825a2f5935df400f63ebbeae552225fc1179e838 # Parent a564634152ae03c65e8201f92ba541e29517c674 subprocessio: don't use __del__ to close the buffers and readers. Instead use a finally block. This helps with GC of resources used by subprocessio. diff --git a/vcsserver/git.py b/vcsserver/git.py --- a/vcsserver/git.py +++ b/vcsserver/git.py @@ -1137,11 +1137,12 @@ class GitRemote(RemoteBase): cmd = [settings.GIT_EXECUTABLE] + _copts + cmd _opts = {'env': gitenv, 'shell': False} + proc = None try: _opts.update(opts) - p = subprocessio.SubprocessIOChunker(cmd, **_opts) + proc = subprocessio.SubprocessIOChunker(cmd, **_opts) - return ''.join(p), ''.join(p.error) + return ''.join(proc), ''.join(proc.error) except (EnvironmentError, OSError) as err: cmd = ' '.join(cmd) # human friendly CMD tb_err = ("Couldn't run git command (%s).\n" @@ -1153,6 +1154,9 @@ class GitRemote(RemoteBase): return '', err else: raise exceptions.VcsException()(tb_err) + finally: + if proc: + proc.close() @reraise_safe_exceptions def install_hooks(self, wire, force=False): diff --git a/vcsserver/subprocessio.py b/vcsserver/subprocessio.py --- a/vcsserver/subprocessio.py +++ b/vcsserver/subprocessio.py @@ -216,9 +216,6 @@ class BufferedGenerator(object): except (GeneratorExit, StopIteration): pass - def __del__(self): - self.close() - #################### # Threaded reader's infrastructure. #################### @@ -475,26 +472,23 @@ class SubprocessIOChunker(object): self._closed = True try: self.process.terminate() - except: + except Exception: pass if self._close_input_fd: os.close(self._close_input_fd) try: self.output.close() - except: + except Exception: pass try: self.error.close() - except: + except Exception: pass try: os.close(self.inputstream) - except: + except Exception: pass - def __del__(self): - self.close() - def run_command(arguments, env=None): """ @@ -506,18 +500,20 @@ def run_command(arguments, env=None): cmd = arguments log.debug('Running subprocessio command %s', cmd) + proc = None try: _opts = {'shell': False, 'fail_on_stderr': False} if env: _opts.update({'env': env}) - p = SubprocessIOChunker(cmd, **_opts) - stdout = ''.join(p) - stderr = ''.join(''.join(p.error)) + proc = SubprocessIOChunker(cmd, **_opts) + return ''.join(proc), ''.join(proc.error) except (EnvironmentError, OSError) as err: cmd = ' '.join(cmd) # human friendly CMD tb_err = ("Couldn't run subprocessio command (%s).\n" "Original error was:%s\n" % (cmd, err)) log.exception(tb_err) raise Exception(tb_err) + finally: + if proc: + proc.close() - return stdout, stderr