#61 Set the “inheritable” flag on MS Windows file handles for system streams.
Opened 2 years ago by bignose. Modified 7 months ago

file modified
+6
@@ -84,6 +84,12 @@ 

  

    Closes: Pagure #72. Thanks to Anton Anton for the report.

  

+ * Set file handles (MS Windows only) of standard streams to be

+   inheritable.

+ 

+   Closes: Pagure #57. Thanks to Juern Brodersen for the report and

+   test case.

+ 

  Added:

  

  * Document a `ServiceRunner` class as an example of using `DaemonContext`.

file modified
+21
@@ -978,6 +978,27 @@ 

      else:

          target_fd = target_stream.fileno()

      os.dup2(target_fd, system_stream.fileno())

+     _set_file_handle_inheritable(target_fd)

+ 

+ 

+ def _set_file_handle_inheritable(handle):

+     """ Set the “inheritable” flag of file handle `handle`.

+ 

+         :param handle: The file handle value.

+         :return: ``None``.

+ 

+         See the Python standard library `os` module. Only the

+         `windows` platform uses file handles; the “inheritable” flag

+         only exists in Python 3.4 or later.

+         """

+     try:

+         set_handle_inheritable = os.set_handle_inheritable

+     except AttributeError:

+         # Not available (and not needed) if Python < 3.4, or if the

+         # platform is not MS Windows.

+         pass

+     else:

+         set_handle_inheritable(handle)

  

  

  def make_default_signal_map():

file modified
+1 -1
@@ -65,7 +65,7 @@ 

              "packaging",

              "lockfile >=0.10",

              ],

-         python_requires=">=3",

+         python_requires=">=3.4",

          extras_require={

              'test': test_requirements,

              'devel': devel_requirements,

file modified
+21
@@ -19,6 +19,7 @@ 

  import sys

  import tempfile

  from types import ModuleType

+ import unittest

  import unittest.mock

  import warnings

  
@@ -375,6 +376,7 @@ 

          self.mock_module_daemon.attach_mock(

                  unittest.mock.Mock(), 'DaemonContext')

  

+         make_fake_streams(self)

          self.test_files_preserve_fds = object()

          self.test_signal_handler_map = object()

          daemoncontext_method_return_values = {
@@ -553,6 +555,25 @@ 

          self.mock_module_daemon.redirect_stream.assert_has_calls(

                  expected_calls, any_order=True)

  

+     @unittest.skipIf(

+             sys.platform != 'windows',

+             "File handles implemented only on MS Windows")

+     @unittest.mock.patch.object(os, "set_inheritable")

+     def test_duplicate_is_inheritable(

+             self, mock_func_os_set_inheritable):

+         """ The system streams should be inheritable.

+ 

+             dup2 sets the new file descriptors to be inhertiable. But if the

+             old and new file descriptors are equal, the inheritable attribute

+             is not changed.

+             If the system streams aren't inheritable they would not be copied

+             to any children of the daemon.

+             """

+         test_stream = self.fake_streams['stdout']

+         stream_fileno = test_stream.fileno()

+         daemon.daemon.redirect_stream(test_stream, test_stream)

+         mock_func_os_set_inheritable.assert_called_with(stream_fileno, True)

+ 

      def test_enters_pidfile_context(self):

          """ Should enter the PID file context manager. """

          instance = self.test_instance

file modified
+1
@@ -10,6 +10,7 @@ 

  import builtins

  import contextlib

  import errno

+ import contextlib

  import io

  import itertools

  import os

This is based on work by @brodersen4univention (request #58).

@brodersen4univention I am unable to exercise this bug (it appears to be specific to the MS Windows platform).

Can you try this with and without the fix, to see that my test case works the way you expect?

Metadata Update from @bignose:
- Pull-request tagged with: more-info
- Request assigned

2 years ago

rebased onto 103f359

7 months ago

rebased onto f477ff1

7 months ago