Mercurial > public > mercurial-scm > hg
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 |