Show More
@@ -306,35 +306,6 b' class server(object):' | |||
|
306 | 306 | |
|
307 | 307 | return 0 |
|
308 | 308 | |
|
309 | def _protectio(uin, uout): | |
|
310 | """Duplicate streams and redirect original to null if (uin, uout) are | |
|
311 | stdio | |
|
312 | ||
|
313 | Returns (fin, fout) which point to the original (uin, uout) fds, but | |
|
314 | may be copy of (uin, uout). The returned streams can be considered | |
|
315 | "owned" in that print(), exec(), etc. never reach to them. | |
|
316 | """ | |
|
317 | uout.flush() | |
|
318 | newfiles = [] | |
|
319 | nullfd = os.open(os.devnull, os.O_RDWR) | |
|
320 | for f, sysf, mode in [(uin, procutil.stdin, r'rb'), | |
|
321 | (uout, procutil.stdout, r'wb')]: | |
|
322 | if f is sysf: | |
|
323 | newfd = os.dup(f.fileno()) | |
|
324 | os.dup2(nullfd, f.fileno()) | |
|
325 | f = os.fdopen(newfd, mode) | |
|
326 | newfiles.append(f) | |
|
327 | os.close(nullfd) | |
|
328 | return tuple(newfiles) | |
|
329 | ||
|
330 | def _restoreio(uin, uout, fin, fout): | |
|
331 | """Restore (uin, uout) streams from possibly duplicated (fin, fout)""" | |
|
332 | uout.flush() | |
|
333 | for f, uif in [(fin, uin), (fout, uout)]: | |
|
334 | if f is not uif: | |
|
335 | os.dup2(f.fileno(), uif.fileno()) | |
|
336 | f.close() | |
|
337 | ||
|
338 | 309 | class pipeservice(object): |
|
339 | 310 | def __init__(self, ui, repo, opts): |
|
340 | 311 | self.ui = ui |
@@ -347,13 +318,13 b' class pipeservice(object):' | |||
|
347 | 318 | ui = self.ui |
|
348 | 319 | # redirect stdio to null device so that broken extensions or in-process |
|
349 | 320 | # hooks will never cause corruption of channel protocol. |
|
350 |
fin, fout = |
|
|
321 | fin, fout = procutil.protectstdio(ui.fin, ui.fout) | |
|
351 | 322 | try: |
|
352 | 323 | sv = server(ui, self.repo, fin, fout) |
|
353 | 324 | return sv.serve() |
|
354 | 325 | finally: |
|
355 | 326 | sv.cleanup() |
|
356 |
|
|
|
327 | procutil.restorestdio(ui.fin, ui.fout, fin, fout) | |
|
357 | 328 | |
|
358 | 329 | def _initworkerprocess(): |
|
359 | 330 | # use a different process group from the master process, in order to: |
@@ -211,6 +211,35 b' def isstdin(f):' | |||
|
211 | 211 | def isstdout(f): |
|
212 | 212 | return _testfileno(f, sys.__stdout__) |
|
213 | 213 | |
|
214 | def protectstdio(uin, uout): | |
|
215 | """Duplicate streams and redirect original to null if (uin, uout) are | |
|
216 | stdio | |
|
217 | ||
|
218 | Returns (fin, fout) which point to the original (uin, uout) fds, but | |
|
219 | may be copy of (uin, uout). The returned streams can be considered | |
|
220 | "owned" in that print(), exec(), etc. never reach to them. | |
|
221 | """ | |
|
222 | uout.flush() | |
|
223 | newfiles = [] | |
|
224 | nullfd = os.open(os.devnull, os.O_RDWR) | |
|
225 | for f, sysf, mode in [(uin, stdin, r'rb'), | |
|
226 | (uout, stdout, r'wb')]: | |
|
227 | if f is sysf: | |
|
228 | newfd = os.dup(f.fileno()) | |
|
229 | os.dup2(nullfd, f.fileno()) | |
|
230 | f = os.fdopen(newfd, mode) | |
|
231 | newfiles.append(f) | |
|
232 | os.close(nullfd) | |
|
233 | return tuple(newfiles) | |
|
234 | ||
|
235 | def restorestdio(uin, uout, fin, fout): | |
|
236 | """Restore (uin, uout) streams from possibly duplicated (fin, fout)""" | |
|
237 | uout.flush() | |
|
238 | for f, uif in [(fin, uin), (fout, uout)]: | |
|
239 | if f is not uif: | |
|
240 | os.dup2(f.fileno(), uif.fileno()) | |
|
241 | f.close() | |
|
242 | ||
|
214 | 243 | def shellenviron(environ=None): |
|
215 | 244 | """return environ with optional override, useful for shelling out""" |
|
216 | 245 | def py2shell(val): |
General Comments 0
You need to be logged in to leave comments.
Login now