Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Daemon Launcher

Turn a process into a well-behaved Unix daemon: detach, redirect stdio, write a pidfile, and optionally relaunch on crash.

Source code:

launch_daemon()

launch_daemon() creates a detached daemon process by performing a double fork and returns the PID of the first child process.

int launch_daemon(
    BOOL redirect_stdio_to_null,
    const char *program,
    ...
);

Parameters

KeyTypeDescription
redirect_stdio_to_nullBOOLIf TRUE, redirects standard input, output, and error to /dev/null.
programconst char *The name of the program to execute as a daemon.
...variadicAdditional arguments to pass to the program, terminated by NULL.

Returns

Returns the PID of the first child process if successful, or -1 if an error occurs.

Notes


Linux daemon supervisor

Declared in ydaemon.h. These entry points run a yuno under a parent “watcher” process that relaunches the child on crash. They are only compiled on Linux (#ifdef __linux__).

daemon_run()

daemon_run() starts the watcher / child supervision loop. The parent process keeps running as a watcher that relaunches the child if it dies. The child calls process(process_name, work_dir, domain_dir, cleaning_fn) to do the actual work.

int daemon_run(
    void (*process)(
        const char *process_name,
        const char *work_dir,
        const char *domain_dir,
        void (*cleaning_fn)(void)
    ),
    const char *process_name,
    const char *work_dir,
    const char *domain_dir,
    void (*cleaning_fn)(void)
);

Parameters

KeyTypeDescription
processfunction pointerEntry point invoked in the child. Receives the process name, work dir, domain dir and the cleanup callback.
process_nameconst char *Name of the process (used in /proc lookups and logs).
work_dirconst char *Working directory to chdir into before running.
domain_dirconst char *Domain-specific directory passed through to the child.
cleaning_fnfunction pointerCleanup callback invoked on shutdown. It can be NULL.

Returns

Returns 0 on normal shutdown, or a non-zero value on error.

Notes


daemon_shutdown()

daemon_shutdown() requests an orderly shutdown of a running daemon by process name. Every process of that name started as it (the base name of argv[0] in /proc/<pid>/cmdline: a script of the same name has its interpreter there and is not one; a daemon whose binary was renamed still is, and so is another user’s, which then fails with EPERM; a zombie of the name is dead and is not counted, nor is an EPERM on one a failure; the list has no fixed size, so look-alikes of the name, which anybody can start, cannot push the real ones out of it) gets SIGQUIT, the watchers first: a watcher notes it and does not relaunch its child, whatever its end; the child shuts down in order and exits 0, and its watcher exits with it. They are given 10 s to be gone; then the name is scanned again and what is left is killed with SIGKILL, said on stderr. Each kill() is checked.

int daemon_shutdown(const char *process_name);

Parameters

KeyTypeDescription
process_nameconst char *Name of the running daemon process to stop.

Returns

0 when every process of the name is gone or killed; -1 when one could not be signalled (another user’s process: EPERM), when the cmdline of one could not be read for a reason other than its end (so it is not known whether it is the daemon), or when the list could not grow (no memory) -- each one said on stderr, and not waited for.

Notes

No-op if no process with the given name is found. The calling process is never signaled. It returns once every process is gone (a zombie counts as gone), so a start that follows does not meet the old one. Up to 7.25.21 each process was killed 1 s after its own SIGQUIT, one after the other: an agent had one second for its orderly shutdown. Up to 7.25.22 it returned nothing: an EPERM waited 10 s, said “killed (SIGKILL)” and the --stop exited 0; and a child that crashed in its shutdown was relaunched by its watcher and left alive once the watcher was killed.

Example

if(arguments.stop) {
    return daemon_shutdown(APP_NAME) < 0? 1 : 0;  // returns when the daemon is gone
}

get_watcher_pid()

get_watcher_pid() returns the PID of the watcher (parent) process that is supervising the current child, or 0 if the caller is not running under a watcher.

int get_watcher_pid(void);

Returns

The watcher process PID, or 0 if the current process has no watcher.


daemon_set_pid_file()

daemon_set_pid_file() names the file where, under --start, the pid of the WATCHER is written -- by the process that was started, before it exits, which is when a systemd unit of Type=forking reads its PIDFile=. The entry point calls it with the value of --pid-file; a yuno has nothing else to do for it.

void daemon_set_pid_file(const char *path);

Parameters

KeyTypeDescription
pathconst char *The file. It must live until daemon_run() (an argv string does). NULL or empty: no file.

Example

/yuneta/agent/yuneta_agent --config-file=/yuneta/agent/yuneta_agent.json \
    --start --pid-file=/run/yuneta_agent/yuneta_agent.pid
cat /run/yuneta_agent/yuneta_agent.pid      # the watcher, the unit's main pid

Notes

The file is written aside (<file>.tmp) and renamed, so systemd reads it whole or not at all. A failure to write it is printed and sent to syslog; the daemon goes on. The unit that uses it is described in the entry point chapter.


get_relaunch_times()

get_relaunch_times() returns the number of times the watcher has relaunched its child process since the daemon was started. Useful for diagnostics and stats endpoints.

int get_relaunch_times(void);

Returns

The relaunch counter (0 on the first run, incremented on each restart).


search_process()

search_process() walks /proc looking for running processes whose name matches process_name and invokes a callback for each match.

int search_process(
    const char *process_name,
    void (*cb)(void *self, const char *name, pid_t pid),
    void *self
);

Parameters

KeyTypeDescription
process_nameconst char *Target process name to match against /proc/*/comm (or /proc/*/cmdline).
cbfunction pointerCallback invoked for each matching process. Receives the opaque self, the resolved process name, and the PID.
selfvoid *Opaque pointer forwarded to the callback.

Returns

Returns the number of matches found, or a negative value on error.

Notes

Used internally by daemon_shutdown() to locate the watcher process to signal.


daemon_set_debug_mode()

daemon_set_debug_mode() enables or disables daemon debug mode for the current process. When debug mode is on the supervisor emits extra tracing and can skip behaviors that will make debugging harder (for example, preventing auto-relaunch on crash).

int daemon_set_debug_mode(BOOL set);

Parameters

KeyTypeDescription
setBOOLTRUE to enable debug mode, FALSE to disable it.

Returns

Returns 0 on success.


daemon_get_debug_mode()

daemon_get_debug_mode() returns whether the daemon is currently running in debug mode.

BOOL daemon_get_debug_mode(void);

Returns

TRUE if debug mode is enabled, FALSE otherwise.