diff --git a/src/calibre/utils/ipc/server.py b/src/calibre/utils/ipc/server.py index 2c31f89ce4..76e7e5a811 100644 --- a/src/calibre/utils/ipc/server.py +++ b/src/calibre/utils/ipc/server.py @@ -6,7 +6,7 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import sys, os, cPickle, time, tempfile, errno +import sys, os, cPickle, time, tempfile, errno, itertools from math import ceil from threading import Thread, RLock from Queue import Queue, Empty @@ -84,7 +84,7 @@ class ConnectedWorker(Thread): class CriticalError(Exception): pass -_name_counter = 0 +_name_counter = itertools.count() if islinux: import fcntl @@ -121,11 +121,9 @@ if islinux: def create_listener(authkey, backlog=4): # Use abstract named sockets on linux to avoid creating unnecessary temp files - global _name_counter prefix = u'\0calibre-ipc-listener-%d-%%d' % os.getpid() while True: - _name_counter += 1 - address = (prefix % _name_counter).encode('ascii') + address = (prefix % next(_name_counter)).encode('ascii') try: l = LinuxListener(address=address, authkey=authkey, backlog=backlog) return address, l @@ -133,13 +131,42 @@ if islinux: if err.errno == errno.EADDRINUSE: continue raise -else: +elif iswindows: + def create_listener(authkey, backlog=4): - address = arbitrary_address('AF_PIPE' if iswindows else 'AF_UNIX') - if iswindows and address[1] == ':': + address = arbitrary_address('AF_PIPE') + if address[1] == ':': address = address[2:] - listener = Listener(address=address, authkey=authkey, backlog=backlog) - return address, listener + return address, Listener(address=address, authkey=authkey, backlog=backlog) +else: + + def create_listener(authkey, backlog=4): + prefix = os.path.join(base_dir(), 'ipc-socket-%d-%%d' % os.getpid()) + max_tries = 20 + while max_tries > 0: + max_tries -= 1 + address = prefix % next(_name_counter) + if not isinstance(address, bytes): + address = address.encode('utf-8') # multiprocessing needs bytes in python 2 + try: + return address, Listener(address=address, authkey=authkey, backlog=backlog) + except EnvironmentError as err: + if max_tries < 1: + raise + + if err.errno == errno.ENOENT: + # Some OS X machines have software that deletes temp + # files/dirs after prolonged inactivity. See for + # example, https://bugs.launchpad.net/bugs/1541356 + try: + os.makedirs(os.path.dirname(prefix)) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + continue + + if err.errno != errno.EADDRINUSE: + raise class Server(Thread):