Mercurial > hg
comparison mercurial/chgserver.py @ 39738:a93fe297dfb3
chgserver: add separate flag to remember if stdio fds are replaced
I want to make it use a separate saved buffer for "attachio" requests within
"runcommand" session. See the next patch for details.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Wed, 19 Sep 2018 22:57:47 +0900 |
parents | a8a902d7176e |
children | 7cdd47d9ccf8 |
comparison
equal
deleted
inserted
replaced
39737:fd805a44b89d | 39738:a93fe297dfb3 |
---|---|
309 def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress): | 309 def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress): |
310 super(chgcmdserver, self).__init__( | 310 super(chgcmdserver, self).__init__( |
311 _newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio), | 311 _newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio), |
312 repo, fin, fout) | 312 repo, fin, fout) |
313 self.clientsock = sock | 313 self.clientsock = sock |
314 self._ioattached = False | |
314 self._oldios = [] # original (self.ch, ui.fp, fd) before "attachio" | 315 self._oldios = [] # original (self.ch, ui.fp, fd) before "attachio" |
315 self.hashstate = hashstate | 316 self.hashstate = hashstate |
316 self.baseaddress = baseaddress | 317 self.baseaddress = baseaddress |
317 if hashstate is not None: | 318 if hashstate is not None: |
318 self.capabilities = self.capabilities.copy() | 319 self.capabilities = self.capabilities.copy() |
322 super(chgcmdserver, self).cleanup() | 323 super(chgcmdserver, self).cleanup() |
323 # dispatch._runcatch() does not flush outputs if exception is not | 324 # dispatch._runcatch() does not flush outputs if exception is not |
324 # handled by dispatch._dispatch() | 325 # handled by dispatch._dispatch() |
325 self.ui.flush() | 326 self.ui.flush() |
326 self._restoreio() | 327 self._restoreio() |
328 self._ioattached = False | |
327 | 329 |
328 def attachio(self): | 330 def attachio(self): |
329 """Attach to client's stdio passed via unix domain socket; all | 331 """Attach to client's stdio passed via unix domain socket; all |
330 channels except cresult will no longer be used | 332 channels except cresult will no longer be used |
331 """ | 333 """ |
335 clientfds = util.recvfds(self.clientsock.fileno()) | 337 clientfds = util.recvfds(self.clientsock.fileno()) |
336 _log('received fds: %r\n' % clientfds) | 338 _log('received fds: %r\n' % clientfds) |
337 | 339 |
338 ui = self.ui | 340 ui = self.ui |
339 ui.flush() | 341 ui.flush() |
340 first = self._saveio() | 342 self._saveio() |
341 for fd, (cn, fn, mode) in zip(clientfds, _iochannels): | 343 for fd, (cn, fn, mode) in zip(clientfds, _iochannels): |
342 assert fd > 0 | 344 assert fd > 0 |
343 fp = getattr(ui, fn) | 345 fp = getattr(ui, fn) |
344 os.dup2(fd, fp.fileno()) | 346 os.dup2(fd, fp.fileno()) |
345 os.close(fd) | 347 os.close(fd) |
346 if not first: | 348 if self._ioattached: |
347 continue | 349 continue |
348 # reset buffering mode when client is first attached. as we want | 350 # reset buffering mode when client is first attached. as we want |
349 # to see output immediately on pager, the mode stays unchanged | 351 # to see output immediately on pager, the mode stays unchanged |
350 # when client re-attached. ferr is unchanged because it should | 352 # when client re-attached. ferr is unchanged because it should |
351 # be unbuffered no matter if it is a tty or not. | 353 # be unbuffered no matter if it is a tty or not. |
360 bufsize = -1 # system default | 362 bufsize = -1 # system default |
361 newfp = os.fdopen(fp.fileno(), mode, bufsize) | 363 newfp = os.fdopen(fp.fileno(), mode, bufsize) |
362 setattr(ui, fn, newfp) | 364 setattr(ui, fn, newfp) |
363 setattr(self, cn, newfp) | 365 setattr(self, cn, newfp) |
364 | 366 |
367 self._ioattached = True | |
365 self.cresult.write(struct.pack('>i', len(clientfds))) | 368 self.cresult.write(struct.pack('>i', len(clientfds))) |
366 | 369 |
367 def _saveio(self): | 370 def _saveio(self): |
368 if self._oldios: | 371 if self._oldios: |
369 return False | 372 return |
370 ui = self.ui | 373 ui = self.ui |
371 for cn, fn, _mode in _iochannels: | 374 for cn, fn, _mode in _iochannels: |
372 ch = getattr(self, cn) | 375 ch = getattr(self, cn) |
373 fp = getattr(ui, fn) | 376 fp = getattr(ui, fn) |
374 fd = os.dup(fp.fileno()) | 377 fd = os.dup(fp.fileno()) |
375 self._oldios.append((ch, fp, fd)) | 378 self._oldios.append((ch, fp, fd)) |
376 return True | |
377 | 379 |
378 def _restoreio(self): | 380 def _restoreio(self): |
379 ui = self.ui | 381 ui = self.ui |
380 for (ch, fp, fd), (cn, fn, _mode) in zip(self._oldios, _iochannels): | 382 for (ch, fp, fd), (cn, fn, _mode) in zip(self._oldios, _iochannels): |
381 newfp = getattr(ui, fn) | 383 newfp = getattr(ui, fn) |