set_close_exec on intermediary server port for unix & windows
Using the win32 API it's possible to prevent the intermediary server socket from inheriting itself to subprocesses. So let's use that here. Another bit of the solution for #2090.
This commit is contained in:
parent
a35e145649
commit
12b8a54081
2 changed files with 58 additions and 11 deletions
|
|
@ -221,14 +221,13 @@ class Server(object):
|
|||
|
||||
### IMPORTANT!
|
||||
###
|
||||
### Do not start any subprocesses until the intermediary server shuts down again or they WILL inherit the
|
||||
### open port and prevent us from firing up Tornado later. Thanks to close_fds not being available on Popen
|
||||
### on Windows if you also want to be able to redirect stdout/stderr/stdin and fnctl also not being available
|
||||
### we don't have a good way around this issue besides being careful not to spawn processes here.
|
||||
### Best do not start any subprocesses until the intermediary server shuts down again or they MIGHT inherit the
|
||||
### open port and prevent us from firing up Tornado later.
|
||||
###
|
||||
### Which kinda sucks tbh.
|
||||
### The intermediary server's socket should have the CLOSE_EXEC flag (or its equivalent) set where possible, but
|
||||
### we can only do that if fcntl is availabel or we are on Windows, so better safe than sorry.
|
||||
###
|
||||
### See also issue #2035
|
||||
### See also issues #2035 and #2090
|
||||
|
||||
# then initialize the plugin manager
|
||||
pluginManager.reload_plugins(startup=True, initialize_implementations=False)
|
||||
|
|
@ -1382,10 +1381,11 @@ class Server(object):
|
|||
bind_and_activate=False)
|
||||
|
||||
# if possible, make sure our socket's port descriptor isn't handed over to subprocesses
|
||||
if fcntl is not None and hasattr(fcntl, "FD_CLOEXEC"):
|
||||
flags = fcntl.fcntl(self._intermediary_server.socket, fcntl.F_GETFD)
|
||||
flags |= fcntl.FD_CLOEXEC
|
||||
fcntl.fcntl(self._intermediary_server.socket, fcntl.F_SETFD, flags)
|
||||
from octoprint.util.platform import set_close_exec
|
||||
try:
|
||||
set_close_exec(self._intermediary_server.fileno())
|
||||
except:
|
||||
self._logger.exception("Error while attempting to set_close_exec on intermediary server socket")
|
||||
|
||||
# then bind the server and have it serve our handler until stopped
|
||||
try:
|
||||
|
|
@ -1395,7 +1395,13 @@ class Server(object):
|
|||
self._intermediary_server.server_close()
|
||||
raise
|
||||
|
||||
thread = threading.Thread(target=self._intermediary_server.serve_forever)
|
||||
def serve():
|
||||
try:
|
||||
self._intermediary_server.serve_forever()
|
||||
except:
|
||||
self._logger.exception("Error in intermediary server")
|
||||
|
||||
thread = threading.Thread(target=serve)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
|
|
|
|||
41
src/octoprint/util/platform/__init__.py
Normal file
41
src/octoprint/util/platform/__init__.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# coding=utf-8
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||||
__copyright__ = "Copyright (C) 2017 The OctoPrint Project - Released under terms of the AGPLv3 License"
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import fcntl
|
||||
except ImportError:
|
||||
fcntl = None
|
||||
|
||||
# set_close_exec
|
||||
|
||||
if fcntl is not None and hasattr(fcntl, "FD_CLOEXEC"):
|
||||
def set_close_exec(handle):
|
||||
flags = fcntl.fcntl(handle, fcntl.F_GETFD)
|
||||
flags |= fcntl.FD_CLOEXEC
|
||||
fcntl.fcntl(handle, fcntl.F_SETFD, flags)
|
||||
|
||||
elif sys.platform == "win32":
|
||||
def set_close_exec(handle):
|
||||
import ctypes
|
||||
import ctypes.wintypes
|
||||
|
||||
# see https://msdn.microsoft.com/en-us/library/ms724935(v=vs.85).aspx
|
||||
SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
|
||||
SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)
|
||||
SetHandleInformation.restype = ctypes.c_bool
|
||||
|
||||
HANDLE_FLAG_INHERIT = 0x00000001
|
||||
|
||||
result = SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0)
|
||||
if not result:
|
||||
raise ctypes.GetLastError()
|
||||
|
||||
else:
|
||||
def set_close_exec(handle):
|
||||
# no-op
|
||||
pass
|
||||
Loading…
Reference in a new issue