Patchwork [V2] sshpeer: store subprocess so it cleans up correctly

mail settings
Submitter Durham Goode
Date March 9, 2013, 2:32 a.m.
Message ID <>
Download mbox | patch
Permalink /patch/1094/
State Accepted
Commit 9baf4330d88f81475cadcfd2041fc100f6cf201f
Headers show


Durham Goode - March 9, 2013, 2:32 a.m.
# HG changeset patch
# User Durham Goode <>
# Date 1362790776 28800
#      Fri Mar 08 16:59:36 2013 -0800
# Node ID a7e8b3306b7ec737c829a85688dc415d7d9215f3
# Parent  2b1729b20820c0eeb0857bb224d009db698faeef
sshpeer: store subprocess so it cleans up correctly

When running 'hg pull --rebase', I was seeing this exception 100% of the
time as the python process was closing down:

Exception TypeError: TypeError("'NoneType' object is not callable",) in
<bound method Popen.__del__ of <subprocess.Popen object at 0x937c10>> ignored

By storing the subprocess on the sshpeer, the subprocess seems to clean up
correctly, and I no longer see the exception. I have no idea why this actually
works, but I get a 0% repro if I store the subprocess in self.subprocess,
and a 100% repro if I store None in self.subprocess.

Possibly related to issue 2240.
Bryan O'Sullivan - March 10, 2013, 12:08 a.m.
On Fri, Mar 08, 2013 at 06:32:06PM -0800, Durham Goode wrote:
> sshpeer: store subprocess so it cleans up correctly

Applied, thanks.


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -70,7 +70,10 @@ 
                 (_serverquote(remotecmd), _serverquote(self.path))))
         ui.note(_('running %s\n') % cmd)
         cmd = util.quotecommand(cmd)
-        self.pipeo, self.pipei, self.pipee = util.popen3(cmd)
+        # while self.subprocess isn't used, having it allows the subprocess to
+        # to clean up correctly later
+        self.pipeo, self.pipei, self.pipee, self.subprocess = util.popen4(cmd)
         # skip any noise generated by remote shell
diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -129,13 +129,17 @@ 
     return p.stdin, p.stdout
 def popen3(cmd, env=None, newlines=False):
+    stdin, stdout, stderr, p = popen4(cmd, env, newlines)
+    return stdin, stdout, stderr
+def popen4(cmd, env=None, newlines=False):
     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-    return p.stdin, p.stdout, p.stderr
+    return p.stdin, p.stdout, p.stderr, p
 def version():
     """Return version information if available."""