Environment: vscode, devcontainers, py3.11 @ debian bookworm image Problem: during either DaemonContext().open(...) or via context manager it's executing until hitting function function called _close_file_descriptor_ranges, where os.closerange(...) fails and ends the program, not execution my application code.
DaemonContext().open(...)
_close_file_descriptor_ranges
os.closerange(...)
tried sudo, doesn't help. minimum code to reproduce:
with DaemonContext(): print("hello")
same behavior on macos15, py3.13 and rhel9.6 py3.11
Howdy Mateusz,
it's executing until hitting function function called _close_file_descriptor_ranges, where os.closerange(...) fails and ends the program
How have you determined that is where the program stops? What is the complete traceback when this failure happens?
Hello Ben,
I've found it via jumping through the code with the debugger. There's no traceback at all, the process is killed instantly with exit code 120. I don't know how to provide more information.
From what i've tested: os.closerange(0, 120) also exits immediately, but os.closerange(120, 256) does not. So, my initial thought was that the range that's being closed is too wide, and maybe it's touching something system-ish
os.closerange(0, 120)
os.closerange(120, 256)
(the range that's being called from the DaemonContext is _close_file_descriptor_ranges(ranges=[0, 1048576]))
DaemonContext
_close_file_descriptor_ranges(ranges=[0, 1048576])
So, my initial thought was that the range that's being closed is too wide, and maybe it's touching something system-ish
Indeed; if there is a file that must remain open when the daemon context starts, you'll need to specify that in the collection specified as the files_preserve option.
files_preserve
When you step through with the debugger, can you make a point to find out which files are currently open, and whether any of those would be critical to the continuing program?
i had a bit more time to test it: os.close(0) kills the interpreter os.close(1) hangs it
os.close(0)
os.close(1)
And both of those descriptors are mapped to the terminal:
$ ls -hla /proc/self/fd total 0 dr-x------ 2 vscode vscode 7 Jun 13 21:17 . dr-xr-xr-x 9 vscode vscode 0 Jun 13 21:17 .. lrwx------ 1 vscode vscode 64 Jun 13 21:17 0 -> /dev/pts/0 lrwx------ 1 vscode vscode 64 Jun 13 21:17 1 -> /dev/pts/0
Therefore, this code solves this issue:
from daemon import DaemonContext with DaemonContext( stdout=open("/dev/stdout", "w"), files_preserve=[ open("/dev/pts/0"), ] ): print("Daemon started")
Shouldn't ignoring the terminal be a default behavior?
@sernick:
Definitely not; the documented behaviour is that the program becomes a daemon process, which entails having no connection to any controlling terminal. By definition, the program will no longer have a way to talk to an interactive terminal.
If you expect an interactive terminal to continue interacting with your program, you are no longer writing a daemon process, but instead you are writing something different for which 'python-daemon' is not designed.
Please re-read the FAQ section on File Descriptors; specifically, on what it means to close all file descriptors by default, and how to continue having standard streams by using the DaemonContext.stdin, DaemonContext.stdout, DaemonContext.stderr options. Note that those new stream objects must be directed somewhere else (e.g., a file on the filesystem), because the process will be explicitly detached from the interactive terminal.
DaemonContext.stdin
DaemonContext.stdout
DaemonContext.stderr
I believe this issue is resolved, by attending to the definition of a daemon process and to the features of DaemonContext for explicitly maintaining open files for communication.
Metadata Update from @bignose: - Issue close_status updated to: Invalid - Issue status updated to: Closed (was: Open)