util: simplify pipefilter and avoid subprocess race
The subprocess module is not thread safe. Spawning a thread to read
the output leads to exceptions like this when Mercurial exits:
Exception exceptions.TypeError: TypeError("'NoneType' object is not
callable",) in <bound method Popen.__del__ of <subprocess.Popen
object at 0x9ed0dcc>> ignored
The bug is already reported in the Python bug tracker:
http://bugs.python.org/
issue1731717
--- a/mercurial/util.py Wed May 06 23:35:20 2009 +0200
+++ b/mercurial/util.py Thu May 07 01:33:44 2009 +0200
@@ -122,23 +122,10 @@
def pipefilter(s, cmd):
'''filter string S through command CMD, returning its output'''
- (pin, pout) = popen2(cmd, 'b')
- def writer():
- try:
- pin.write(s)
- pin.close()
- except IOError, inst:
- if inst.errno != errno.EPIPE:
- raise
-
- # we should use select instead on UNIX, but this will work on most
- # systems, including Windows
- w = threading.Thread(target=writer)
- w.start()
- f = pout.read()
- pout.close()
- w.join()
- return f
+ p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ pout, perr = p.communicate(s)
+ return pout
def tempfilter(s, cmd):
'''filter string S through a pair of temporary files with CMD.