Your caracteristics are way too restrictive. The key notion here is: a daemon is a background process, therefore it cannot be the controlling process of a terminal, nor can it have a controlling terminal. This simple "rule" allows daemons to survive across terminals open/close and users login/logout.
Each terminal has a controlling session, that is, a set of processes that were spawned through that terminal. The session leader, usually a shell, is the terminal's controlling process. The terminal is said to be the shell's controlling terminal.
As you'll be able to read in this answer to one of my questions, when a terminal is closed, it sends a SIGHUP
signal to its controlling process, the shell. This usually causes all process attached to this shell to die, as the shell will retransmit the SIGHUP
it received to all its jobs.
Daemon processes must escape this chain as they ought to survive users logins and logouts. For this reason, they have to detach themselves from their parent shell. A common way to do so is to double fork.
- The daemon spawns a child process.
- The daemon exits its "main"/parent process.
- All the work is done in the child.
Since shells do not keep tracks of their grandchildren, they won't send a SIGHUP
to the remaining piece of the daemon. Now, in this setup, the grandchildren (daemon) should basically have:
- Its own PID, as any other process.
- The PGID of its now-terminated parent.
- The PPID of its nearest subreaper, usually PID 1.
- The SID of its now-terminated parent, which is usually the shell's SID as well.
Note that killing the parent wasn't particularly necessary: the process would have died with its terminal. However, to avoid useless processes, it is a little cleaner to terminate the parent immediately, before the child starts working.
In this situation, the process can be called a daemon. Closing the terminal won't kill it. However, it is very common to give a brand new session to daemon processes. At the API level, this is done using the setsid
system call. Once it has been used, the process should have:
- An unchanged PID.
- An unchanged PPID (nearest subreaper).
- A brand new SID, usually the same as its PID.
- A brand new GID, since processes from the same group must also be in the same session.
fork
after thesetsid
to avoid being a session leader, so that if ever the process opens a file and that file happens to be a tty device and you forgot to pass the the O_NOCTTY flag, it doesn't end up controlling the terminal. (which is why it's not uncommon to havesid != pid
for a daemon, for instance Debian'sstart-stop-daemon -b
does that). – Stéphane Chazelas Dec 19 '14 at 13:57