4646CONNECTION_TIMEOUT = 20.
4747
4848_mmap_counter = itertools.count()
49+ _MAX_PIPE_ATTEMPTS = 100
4950
5051default_family = 'AF_INET'
5152families = ['AF_INET']
@@ -78,8 +79,8 @@ def arbitrary_address(family):
7879 elif family == 'AF_UNIX':
7980 return tempfile.mktemp(prefix='sock-', dir=util.get_temp_dir())
8081 elif family == 'AF_PIPE':
81- return tempfile.mktemp(prefix= r'\\.\pipe\pyc-%d-%d-' %
82- (os.getpid(), next(_mmap_counter)), dir="" )
82+ return ( r'\\.\pipe\pyc-%d-%d-%s ' %
83+ (os.getpid(), next(_mmap_counter), os.urandom(8).hex()) )
8384 else:
8485 raise ValueError('unrecognized family')
8586
@@ -472,17 +473,29 @@ class Listener(object):
472473 def __init__(self, address=None, family=None, backlog=1, authkey=None):
473474 family = family or (address and address_type(address)) \
474475 or default_family
475- address = address or arbitrary_address(family)
476-
477476 _validate_family(family)
477+ if authkey is not None and not isinstance(authkey, bytes):
478+ raise TypeError('authkey should be a byte string')
479+
478480 if family == 'AF_PIPE':
479- self._listener = PipeListener(address, backlog)
481+ if address:
482+ self._listener = PipeListener(address, backlog)
483+ else:
484+ for attempts in itertools.count():
485+ address = arbitrary_address(family)
486+ try:
487+ self._listener = PipeListener(address, backlog)
488+ break
489+ except OSError as e:
490+ if attempts >= _MAX_PIPE_ATTEMPTS:
491+ raise
492+ if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
493+ _winapi.ERROR_ACCESS_DENIED):
494+ raise
480495 else:
496+ address = address or arbitrary_address(family)
481497 self._listener = SocketListener(address, family, backlog)
482498
483- if authkey is not None and not isinstance(authkey, bytes):
484- raise TypeError('authkey should be a byte string')
485-
486499 self._authkey = authkey
487500
488501 def accept(self):
@@ -570,7 +583,6 @@ def Pipe(duplex=True):
570583 '''
571584 Returns pair of connection objects at either end of a pipe
572585 '''
573- address = arbitrary_address('AF_PIPE')
574586 if duplex:
575587 openmode = _winapi.PIPE_ACCESS_DUPLEX
576588 access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
@@ -580,15 +592,25 @@ def Pipe(duplex=True):
580592 access = _winapi.GENERIC_WRITE
581593 obsize, ibsize = 0, BUFSIZE
582594
583- h1 = _winapi.CreateNamedPipe(
584- address, openmode | _winapi.FILE_FLAG_OVERLAPPED |
585- _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE,
586- _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
587- _winapi.PIPE_WAIT,
588- 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER,
589- # default security descriptor: the handle cannot be inherited
590- _winapi.NULL
591- )
595+ for attempts in itertools.count():
596+ address = arbitrary_address('AF_PIPE')
597+ try:
598+ h1 = _winapi.CreateNamedPipe(
599+ address, openmode | _winapi.FILE_FLAG_OVERLAPPED |
600+ _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE,
601+ _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
602+ _winapi.PIPE_WAIT,
603+ 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER,
604+ # default security descriptor: the handle cannot be inherited
605+ _winapi.NULL
606+ )
607+ break
608+ except OSError as e:
609+ if attempts >= _MAX_PIPE_ATTEMPTS:
610+ raise
611+ if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
612+ _winapi.ERROR_ACCESS_DENIED):
613+ raise
592614 h2 = _winapi.CreateFile(
593615 address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,
594616 _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL
0 commit comments