Schottky
Schottky

Reputation: 2024

Process inside daemon immediately exits when using FIFO

I have a setup that looks roughly like the following example:

from contextlib import contextmanager
import subprocess
import os
from pathlib import Path

import daemon


@contextmanager
def tmp_fifo(path: Path):
    try:
        os.mkfifo(path)
        file = os.open(path, os.O_RDWR | os.O_NONBLOCK)
        yield file
    finally:
        os.unlink(path)


with tmp_fifo(Path.home() / "sh.fifo") as fifo, open("dout.log", "w+") as outfile:
    context = daemon.DaemonContext()
    with context:
        with subprocess.Popen(["sh"], stdin=fifo, stdout=outfile) as popen:
            popen.wait()

Essentially, what I am trying to do is to forward a shell to a FIFO. Without daemonizing, this works; i.e., I could write

from contextlib import contextmanager
import subprocess
import os
from pathlib import Path


@contextmanager
def tmp_fifo(path: Path):
    try:
        os.mkfifo(path)
        file = os.open(path, os.O_RDWR | os.O_NONBLOCK)
        yield file
    finally:
        os.unlink(path)


with tmp_fifo(Path.home() / "sh.fifo") as fifo, open("dout.log", "w+") as outfile:
    with subprocess.Popen(["sh"], stdin=fifo, stdout=outfile) as popen:
        popen.wait()

which allows me to input commands in the FIFO and see the results in the log file. How do I reproduce the desired behavior using a daemon? I tried moving the file redirects to the DaemonContext constructor, but that doesn't help. I also looked through the configuration options but none seem to be applicable.

Upvotes: 0

Views: 72

Answers (1)

Austin Duling
Austin Duling

Reputation: 473

You may need to try moving the FIFO and log file handling into the daemon context. Try something like the following:

from contextlib import contextmanager
import subprocess
import os
from pathlib import Path
import daemon

@contextmanager
def tmp_fifo(path: Path):
    try:
        os.mkfifo(path)
        file = os.open(path, os.O_RDWR | os.O_NONBLOCK)
        yield file
    finally:
        os.unlink(path)

def run_daemonized_shell():
    fifo_path = Path.home() / "sh.fifo"
    log_path = "dout.log"

    # Setup the daemon context FIRST
    with daemon.DaemonContext():
        with tmp_fifo(fifo_path) as fifo:
            with open(log_path, "w+") as outfile:
                with subprocess.Popen(["sh"], stdin=fifo, stdout=outfile) as popen:
                    popen.wait()

if __name__ == "__main__":
    run_daemonized_shell()

Upvotes: 1

Related Questions