Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commandserver.py @ 33503:27d23fe32887
commandserver: use selectors2
Previously, commandserver was using select.select. That could have issue if
_sock.fileno() >= FD_SETSIZE (usually 1024), which raises:
ValueError: filedescriptor out of range in select()
We got that in production today, although it's the code opening that many
files to blame, it seems better for commandserver to work in this case.
There are multiple way to "solve" it, like preserving a fd with a small
number and swap it with sock using dup2(). But upgrading to a modern
selector supported by the system seems to be the most correct way.
author | Jun Wu <quark@fb.com> |
---|---|
date | Fri, 14 Jul 2017 20:26:21 -0700 |
parents | 0407a51b9d8c |
children | 8a1a7935c047 |
comparison
equal
deleted
inserted
replaced
33502:5d0c0c8d2929 | 33503:27d23fe32887 |
---|---|
20 from .i18n import _ | 20 from .i18n import _ |
21 from . import ( | 21 from . import ( |
22 encoding, | 22 encoding, |
23 error, | 23 error, |
24 pycompat, | 24 pycompat, |
25 selectors2, | |
25 util, | 26 util, |
26 ) | 27 ) |
27 | 28 |
28 logfile = None | 29 logfile = None |
29 | 30 |
474 self._cleanup() | 475 self._cleanup() |
475 | 476 |
476 def _mainloop(self): | 477 def _mainloop(self): |
477 exiting = False | 478 exiting = False |
478 h = self._servicehandler | 479 h = self._servicehandler |
480 selector = selectors2.DefaultSelector() | |
481 selector.register(self._sock, selectors2.EVENT_READ) | |
479 while True: | 482 while True: |
480 if not exiting and h.shouldexit(): | 483 if not exiting and h.shouldexit(): |
481 # clients can no longer connect() to the domain socket, so | 484 # clients can no longer connect() to the domain socket, so |
482 # we stop queuing new requests. | 485 # we stop queuing new requests. |
483 # for requests that are queued (connect()-ed, but haven't been | 486 # for requests that are queued (connect()-ed, but haven't been |
484 # accept()-ed), handle them before exit. otherwise, clients | 487 # accept()-ed), handle them before exit. otherwise, clients |
485 # waiting for recv() will receive ECONNRESET. | 488 # waiting for recv() will receive ECONNRESET. |
486 self._unlinksocket() | 489 self._unlinksocket() |
487 exiting = True | 490 exiting = True |
488 try: | 491 try: |
489 ready = select.select([self._sock], [], [], h.pollinterval)[0] | 492 ready = selector.select(timeout=h.pollinterval) |
490 if not ready: | 493 if not ready: |
491 # only exit if we completed all queued requests | 494 # only exit if we completed all queued requests |
492 if exiting: | 495 if exiting: |
493 break | 496 break |
494 continue | 497 continue |