From 50abe4d91311898d8c0d1c04ceeb2a1f650c15ab Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Fri, 29 Nov 2013 11:11:49 +0100 Subject: [PATCH] Fix for bug #1256198 --- .../devices/smart_device_app/driver.py | 4 ++ src/calibre/utils/socket_inheritance.py | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/calibre/utils/socket_inheritance.py diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index 23742830c6..44b1852437 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -38,6 +38,7 @@ from calibre.utils.config_base import tweaks from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to from calibre.utils.mdns import (publish as publish_zeroconf, unpublish as unpublish_zeroconf, get_all_ips) +from calibre.utils.socket_inheritance import set_socket_inherit def synchronous(tlockname): """A decorator to place an instance based lock around a method """ @@ -139,6 +140,7 @@ class ConnectionListener(Thread): self.driver.listen_socket.accept) self.driver.listen_socket.settimeout(None) device_socket.settimeout(None) + set_socket_inherit(device_socket, False) try: self.driver.connection_queue.put_nowait(device_socket) @@ -1480,7 +1482,9 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): message = None try: self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + set_socket_inherit(self.listen_socket, False) except: + traceback.print_exc() message = 'creation of listen socket failed' self._debug(message) return message diff --git a/src/calibre/utils/socket_inheritance.py b/src/calibre/utils/socket_inheritance.py new file mode 100644 index 0000000000..f27d56c9ef --- /dev/null +++ b/src/calibre/utils/socket_inheritance.py @@ -0,0 +1,59 @@ +''' +Created on 29 Nov 2013 + +@author: charles + +Code taken from https://mail.python.org/pipermail/python-dev/2007-June/073745.html +modified to make it work +''' + +import os, traceback + +def get_socket_inherit(socket): + ''' + Returns True if the socket has been set to allow inheritance across + forks and execs to child processes, otherwise False + ''' + try: + if os.name == "nt": + import win32api, win32con + flags = win32api.GetHandleInformation(socket.fileno()) + return bool(flags & win32con.HANDLE_FLAG_INHERIT) + else: + import fcntl + flags = fcntl.fcntl(socket.fileno(), fcntl.F_GETFD) + return not bool(flags & fcntl.FD_CLOEXEC) + except: + traceback.print_exc() + +def set_socket_inherit(sock, inherit): + ''' + Mark a socket as inheritable or non-inheritable to child processes. + + This should be called right after socket creation if you want + to prevent the socket from being inherited by child processes. + + Note that for sockets, a new socket returned from accept() will be + inheritable even if the listener socket was not; so you should call + set_socket_inherit for the new socket as well. + ''' + try: + if os.name == "nt": + import win32api, win32con + + if inherit: + flags = win32con.HANDLE_FLAG_INHERIT + else: + flags = 0 + win32api.SetHandleInformation(sock.fileno(), + win32con.HANDLE_FLAG_INHERIT, flags) + else: + import fcntl + + fd = sock.fileno() + flags = fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC + if not inherit: + flags = flags | fcntl.FD_CLOEXEC + fcntl.fcntl(fd, fcntl.F_SETFD, flags) + except: + traceback.print_exc() \ No newline at end of file