diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 8c5ab82cd1..2a5fd0ebc1 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -418,13 +418,11 @@ def communicate(opts, args): raise SystemExit(0) def create_listener(): - from multiprocessing.connection import Listener - listener = Listener(address=gui_socket_address()) - if islinux and hasattr(listener._listener._unlink, 'cancel'): - # multiprocessing tries to call unlink even on abstract - # named sockets, prevent it from doing so. - listener._listener._unlink.cancel() - return listener + if islinux: + from calibre.utils.ipc.server import LinuxListener as Listener + else: + from multiprocessing.connection import Listener + return Listener(address=gui_socket_address()) def main(args=sys.argv): gui_debug = None diff --git a/src/calibre/utils/ipc/server.py b/src/calibre/utils/ipc/server.py index 6ee83ddf34..3e00a15ef0 100644 --- a/src/calibre/utils/ipc/server.py +++ b/src/calibre/utils/ipc/server.py @@ -87,6 +87,22 @@ class CriticalError(Exception): _name_counter = 0 if islinux: + class LinuxListener(Listener): + + def __init__(self, *args, **kwargs): + Listener.__init__(self, *args, **kwargs) + # multiprocessing tries to call unlink even on abstract + # named sockets, prevent it from doing so. + self._listener._unlink.cancel() + + def close(self): + # To ensure that the socket is released, we have to call + # shutdown() not close(). This is needed to allow calibre to + # restart using the same socket address. + import socket + self._listener._socket.shutdown(socket.SHUT_RDWR) + self._listener._socket.close() + def create_listener(authkey, backlog=4): # Use abstract named sockets on linux to avoid creating unnecessary temp files global _name_counter @@ -95,11 +111,7 @@ if islinux: _name_counter += 1 address = (prefix % _name_counter).encode('ascii') try: - l = Listener(address=address, authkey=authkey, backlog=backlog) - if hasattr(l._listener._unlink, 'cancel'): - # multiprocessing tries to call unlink even on abstract - # named sockets, prevent it from doing so. - l._listener._unlink.cancel() + l = LinuxListener(address=address, authkey=authkey, backlog=backlog) return address, l except EnvironmentError as err: if err.errno == errno.EADDRINUSE: