#89 file with no fileno
Opened by mennucc. Modified

dear developer,

I had a traceback, as follows

Traceback (most recent call last):
  File "/home/rsyncd/post_backup", line 106, in <module>
    with daemon.DaemonContext(working_directory=here, stdout=out, stderr=out):
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/daemon/daemon.py", line 249, in __init__
    detach_process = is_detach_process_context_required()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/daemon/daemon.py", line 817, in is_detach_process_context_required
    if is_process_started_by_init() or is_process_started_by_superserver():
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/daemon/daemon.py", line 795, in is_process_started_by_superserver
    if is_socket_file(sys.__stdin__):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/daemon/daemon.py", line 759, in is_socket_file
    file_fd = file.fileno()
              ^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'fileno'

I solved it with this patch

--- /usr/lib/python3/dist-packages/daemon/daemon.py~    2022-07-19 02:18:18.000000000 +0000
+++ /usr/lib/python3/dist-packages/daemon/daemon.py     2024-02-18 19:53:32.055404205 +0000
@@ -757,9 +757,9 @@
     try:
         file_fd = file.fileno()
-    except ValueError:
+    except (ValueError, AttributeError):
         # The file doesn't have a file descriptor.
-        file_fd = None
+        return False
     try:
         file_socket = socket.fromfd(file_fd, socket.AF_INET, socket.SOCK_RAW)

regards


Howdy Andrea,

On 18-Feb-2024, Andrea Mennucci wrote:

I had a traceback, as follows

What led to this? It seems that sys.__stdin__ is the None object; how
did this happen?

AttributeError: 'NoneType' object has no attribute 'fileno'

This seems like the correct behaviour when this unusual circumstance
happens; the program is in a very unusual state (the sys.__stdin__ should
never be modified from its original value), and crashing with a message to
inform of this, seems appropriate.

--=20
\ =E2=80=9CSome mornings, it's just not worth chewing through the leat=
her |
`\ straps.=E2=80=9D =E2=80=94=
Emo Philips |
_o__) |
Ben Finney ben@benfinney.id.au

according to the documentation
https://docs.python.org/3/library/sys.html#sys.stdout

Note: Under some conditions stdin, stdout and stderr as well as the original values stdin, stdout and stderr can be None.

here is a code that (on Ubuntu 22.04) will get sys.stdin=None

save this as "first.py"

#!/usr/bin/python3
import sys, os
os.close(sys.stdin.fileno())
print('first exec second')
os.execvp(os.path.abspath('second.py'), ['second.py'])

save this as "second.py"

#!/usr/bin/python3
import sys
print('second running')
print('stdin is ', sys.stdin)

output

first exec second
second running
stdin is  None

now if you add

out = open('/tmp/daemon.log', 'a')
with daemon.DaemonContext(working_directory='/tmp', stdout=out, stderr=out):
    print('daemon OK')

at the end of "second.py", you get a traceback from "daemon" code

ignore the patch in my first post... yes no traceback happens, ... but the code in the DaemonContext is not executed

currently I prepend the call to daemon with the following snippet

if sys.stdin is None:
    O = open(os.devnull)
    sys.stdin = sys.__stdin__ = O
    try:
        os.stat(0)
    except OSError:
        os.dup2(O.fileno, 0)

maybe this code may be integrated into daemon

Metadata