57 import threading |
57 import threading |
58 import killdaemons as killmod |
58 import killdaemons as killmod |
59 import Queue as queue |
59 import Queue as queue |
60 |
60 |
61 processlock = threading.Lock() |
61 processlock = threading.Lock() |
62 waitlock = threading.Lock() |
62 |
63 |
63 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24 |
64 def waitlocked(fn): |
64 # http://bugs.python.org/issue1731717 for details. We shouldn't be producing |
65 def run(): |
65 # zombies but it's pretty harmless even if we do. |
66 waitlock.acquire() |
66 if sys.version_info[1] < 5: |
67 ret = fn() |
67 subprocess._cleanup = lambda: None |
68 waitlock.release() |
|
69 return ret |
|
70 return run |
|
71 |
68 |
72 closefds = os.name == 'posix' |
69 closefds = os.name == 'posix' |
73 def Popen4(cmd, wd, timeout, env=None): |
70 def Popen4(cmd, wd, timeout, env=None): |
74 processlock.acquire() |
71 processlock.acquire() |
75 p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env, |
72 p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env, |
76 close_fds=closefds, |
73 close_fds=closefds, |
77 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
74 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
78 stderr=subprocess.STDOUT) |
75 stderr=subprocess.STDOUT) |
79 if sys.version_info[1] < 5: |
|
80 p.wait = waitlocked(p.wait) |
|
81 p.poll = waitlocked(p.poll) |
|
82 processlock.release() |
76 processlock.release() |
83 |
77 |
84 p.fromchild = p.stdout |
78 p.fromchild = p.stdout |
85 p.tochild = p.stdin |
79 p.tochild = p.stdin |
86 p.childerr = p.stderr |
80 p.childerr = p.stderr |