#100 Closing file descriptor ranges fails
Closed: Invalid by bignose. Opened by sernick.

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.

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

(the range that's being called from the DaemonContext is _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.

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

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:

Shouldn't ignoring the terminal be a default behavior?

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.

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)

Metadata