nx_daemon.nx source
↩ module page · 26 lines · 1521 B
1// nx_daemon.nx -- canonical sovereign detached-spawn: launch an elf as a daemon that survives the parent (new
2// session via setsid), the sovereign run_in_background. Importable (no main). fork -> child setsid()s then execve()s;
3// parent gets the child pid. Same sys_fork/nx_setsid/sys_execve nx_hostctl uses to supervise its NAS daemons.
4// license_tier: ORIGINAL
5import "nx_syscalls.nx"
6
7// spawn `elf` with `argv` (a NUL-terminated *i64 array of *u8 pointers) DETACHED. Returns child pid (>0) in the
8// parent, 0 should never be seen (child execve's or exits), <0 on fork failure. envp=0 -> empty environment.
9func daemon_spawn(elf: *u8, argv: *i64) -> i64 {
10 let pid: i64 = sys_fork()
11 if pid == 0 {
12 nx_setsid()
13 // FULLY daemonize: detach the std fds so the child can't die of SIGPIPE when the launcher's pipe closes,
14 // and so it has no controlling terminal. stdin <- /dev/null, stdout+stderr -> /tmp/nxd.log (a real log).
15 let din: i64 = sys_openat_rd("/dev/null" as *u8)
16 let dlog: i64 = sys_openat_wr("/tmp/nxd.log" as *u8, 0x1a4)
17 if din >= 0 { sys_dup3(din, 0, 0) }
18 if dlog >= 0 { sys_dup3(dlog, 1, 0); sys_dup3(dlog, 2, 0) }
19 sys_execve(elf, argv, 0 as *i64)
20 sys_exit(127) // only reached if execve failed
21 }
22 return pid
23}
24
25// build a 2-entry argv [elf, 0] for the common no-args daemon case; argv must be >= 2 i64 slots.
26func daemon_argv0(elf: *u8, argv: *i64) -> i64 { argv[0] = elf as i64; argv[1] = 0; return 0 }