| 409 | current = None |
| 410 | |
| 411 | def __init__(self, host, port=9190, port_end=9199, silent=False, reuse_addr=True, timeout=None): |
| 412 | if silent: |
| 413 | logger.setLevel(logging.WARN) |
| 414 | |
| 415 | sock = socket.socket(base.get_addr_family((host, port)), socket.SOCK_STREAM) |
| 416 | |
| 417 | # Never set socket SO_REUSEADDR on Windows. The SO_REUSEADDR flag allow reusing the |
| 418 | # inactivate TIME_WATI state sockets on POSIX, but on Windows it will allow two or more |
| 419 | # activate sockets to bind on the same address and port if they all set SO_REUSEADDR, |
| 420 | # and result in indeterminate behavior. |
| 421 | if reuse_addr and sys.platform != "win32": |
| 422 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 423 | if timeout is not None: |
| 424 | sock.settimeout(timeout) |
| 425 | self.port = None |
| 426 | self.stop_key = base.random_key("tracker") |
| 427 | for my_port in range(port, port_end): |
| 428 | try: |
| 429 | sock.bind((host, my_port)) |
| 430 | self.port = my_port |
| 431 | break |
| 432 | except OSError as sock_err: |
| 433 | if sock_err.errno in [errno.EADDRINUSE]: |
| 434 | continue |
| 435 | raise sock_err |
| 436 | if not self.port: |
| 437 | raise ValueError(f"cannot bind to any port in [{port}, {port_end})") |
| 438 | logger.info("bind to %s:%d", host, self.port) |
| 439 | sock.listen(1) |
| 440 | self.thread = threading.Thread(target=_tracker_server, args=(sock, self.stop_key)) |
| 441 | self.thread.start() |
| 442 | self.host = host |
| 443 | |
| 444 | |
| 445 | def _popen_start_tracker_server( |