From 8a902e7810d20869691e1e06811ea39cd7ac0417 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 28 Mar 2014 10:42:00 +0530 Subject: [PATCH] Fix abstract named socket used for GUI IPC on linux not being shutdown till process exit, thereby preventing restart from working. Fixes #1298756 [error restarting](https://bugs.launchpad.net/calibre/+bug/1298756) --- src/calibre/gui2/main.py | 12 +++++------- src/calibre/utils/ipc/server.py | 22 +++++++++++++++++----- 2 files changed, 22 insertions(+), 12 deletions(-) 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: