comparison mercurial/chgserver.py @ 45035:3862de62d5cf

chg: suppress OSError in _restoreio() and add some logging (issue6330) According to issue6330, running chg on heavy loaded systems can lead to following error: ``` Traceback (most recent call last): File "path-to-hg/mercurial/commandserver.py", line 650, in _acceptnewconnection self._runworker(conn) File "path-to-hg/mercurial/commandserver.py", line 701, in _runworker prereposetups=[self._reposetup], File "path-to-hg/mercurial/commandserver.py", line 470, in _serverequest sv.cleanup() File "path-to-hg/mercurial/chgserver.py", line 381, in cleanup self._restoreio() File "path-to-hg/mercurial/chgserver.py", line 444, in _restoreio os.dup2(fd, fp.fileno()) OSError: [Errno 16] Device or resource busy ``` [man dup2] indicates that, on Linux, EBUSY comes from a race condition between open() and dup2(). However it's not clear why open() race occurred for newfd=stdin/out/err. We suppress the OSError in _restoreio() since the forked worker process will finish anyway and add some logging. Thanks to Mitchell Plamann for a detailed bug description and Yuya Nishihara for suggesting the fix.
author Pulkit Goyal <7895pulkit@gmail.com>
date Fri, 03 Jul 2020 13:45:59 +0530
parents 8e8fd938ca07
children a17454a189d1
comparison
equal deleted inserted replaced
45033:b4b6ff83ed9c 45035:3862de62d5cf
440 # close newfp while it's associated with client; otherwise it 440 # close newfp while it's associated with client; otherwise it
441 # would be closed when newfp is deleted 441 # would be closed when newfp is deleted
442 if newfp is not fp: 442 if newfp is not fp:
443 newfp.close() 443 newfp.close()
444 # restore original fd: fp is open again 444 # restore original fd: fp is open again
445 os.dup2(fd, fp.fileno()) 445 try:
446 os.dup2(fd, fp.fileno())
447 except OSError as err:
448 # According to issue6330, running chg on heavy loaded systems
449 # can lead to EBUSY. [man dup2] indicates that, on Linux,
450 # EBUSY comes from a race condition between open() and dup2().
451 # However it's not clear why open() race occurred for
452 # newfd=stdin/out/err.
453 self.ui.log(
454 b'chgserver',
455 b'got %s while duplicating %s\n',
456 stringutil.forcebytestr(err),
457 fn,
458 )
446 os.close(fd) 459 os.close(fd)
447 setattr(self, cn, ch) 460 setattr(self, cn, ch)
448 setattr(ui, fn, fp) 461 setattr(ui, fn, fp)
449 del self._oldios[:] 462 del self._oldios[:]
450 463