Understanding Daemons
blog.digitalbunker.dev
blog.digitalbunker.dev
further reading https://www.man7.org/linux/man-pages/man7/daemon.7.html
Just write your server as a straightforward process and let the service manager handle this stuff for you. You'll just be confusing it if you don't.
The people who keep complaining about it seem more and more like children who just refuse to learn something new and better because they've already stumbled through all the holes it fills.
Systemd apologists always seems to think that anyone not completely in love with systemd, is just refusing to learn something new. Please stop with the stupidity, people have real reasons to hate that shit.
I had no problem with switching to WireGuard, after learning about it, because this is so much better in both use and design than OpenVPN that I have used for 20 years. I had no problem with learning about systemd either, but that is just badly designed software to me.
(And was just wondering if there was any specific thing the original parent wanted to replace.)
Again, was just interested if you had any specific thing you could point to, but elsewhere in the comments I see now a few concrete issues.
You can easily replace timesyncd with any NTP daemon. You can easily replace networkd with any other networking manager. You can easily replace timer units with cron. You can easily forward log messages to a syslog daemon. You can easily replace systemd-boot with grub or any other boot manager.
It should be pretty obvious how baseless the monolithic arguments against systemd are.
Would be funny if people made the same complaint about the various GNU core utils because those are all installed from the same package on most (all?) distros.
Systemd is good init replacement, ok ntp replacement, so-so logging deamon replacement , and shitty DNS resolver replacement.
I like the init part, i could do without everything else.
But the thing I hate the most about it is that if you question any part of it like DNS, you are labeled as a systemd hater.
So I have to find workarounds, like intercepting DNS queries on network level, to fix what used to work before.
And if dnssec ever gets implemented, that wont work either.
Also, dnssec is implemented, and it works.
I wrote whole wall of text but at the end of the day, its not that big of a deal, It's more annoying explaing to customers that they have to talk to their other vendors to fix their configs, so sometimes just network level hack is easier.
[1] In enterprise environment and even some SMB environment its somewhat common (at least here in South EU) that big vendors just drop black boxes to you (usually in a form of vmware image, lately sometimes Docker containers). A lot of them are just stock RH, or Ubuntu with their software. ANd that comes with default fallback to goolge or cloudfalre DNS's
Before systemd, you just needed to set correct DHCP config and it would all just work.
But nowdays distros come with systemd-resolved which usualy has (by deafult) fallback public DNS servers.
That means that boxes suddenly can switch from your DHCP network provided DNS servers (or even static DNS servers) to goolge (or cloudflare,) public DNS server.
Bottom line is, it used to be enough to set DNS server through DHCP (or static ones) that is no longer enough in some situations.
Then, do exactly that? None of the components you're complaining about are mandatory (except for journald, but you can easily forward log messages to a regular syslog daemon).
Often that's not an option and have to create workarounds on network level (for DNS).
Because I might not have a say on what device is running, but if it can't resolve internal systems its my problem.
DNSSEC is going to make my life even more interesting.
"We need a process without a process group, session, controlling terminal and mount point. How to do that? Well, fork two times, setsid, chdir, close all descriptors. Let's call that daemon for short."
If one does not understand what all of this really means, or why all of this is part of a question, who do they blame against learning something new?
Also, if you're not starting from a login session, do you really need to double fork?
Also I just downloaded the recent sources of sshd and it does daemon(0, 0) under the hood, unless -D is passed. ssh.service just runs it with -D, so what's the deal? Does one function call for the case when systemd is not there break some religion?
https://github.com/openssh/openssh-portable/blob/V_8_3/sshd....
It was a technically superior solution murdered by politics.
What's worse was all of the people who were going "why are you moaning? what's wrong? systemd is still an improvement on sysvinit!" as if being better than a bunch of bash scripts held together with bits of sticky tape and string was all the qualification needed to be PID 1.
http://0pointer.net/blog/projects/systemd
(See heading “On Upstart”)
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727708#172...
And yes, people do erroneously paint it as only a choice between van Smoorenburg init+rc and systemd, as if they were the only two possibilities, when in fact in the Debian Hoo-Hah (for one) it was effectively a choice between systemd, upstart, and OpenRC, nearly all parties agreeing at one point in the proceedings that van Smoorenburg init+rc was last choice, either before or after "further discussion".
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727708#672...
Moreover, I'm not really so sure a couple of those features even belong in an init system.
Debian's decision effectively doomed upstart and led to an init system monoculture. The practical upshot is that no competition for systemd means no pressure to improve. Even for systemd it was a bad decision.
One cannot truly portray this as either "politics" or only about lack of features.
* http://jdebp.uk./FGA/debian-systemd-packaging-hoo-hah.html
* http://jdebp.uk./FGA/unix-daemon-readiness-protocol-problems...
In practice, service managers have been around since 1988.
A memorable way to think about this is that a daemon is a child process whose parent has literally disowned it, forked off, and died.
* https://unix.stackexchange.com/a/606902/5132
Thinking that forking makes a dæmon is much the same error as thinking that su drops privileges, it conflates what happend to be a mechanism from years ago with the actual purpose, totally missing that things have changed since (long since, decades ago in fact).
Fortunately I recently replaced my lost 1st edition with a 2nd edition, and the coverage looks similar. From what I can see there are two details left out of this article:
* Why changing the working directory is important (so the daemon doesn’t accidentally prevent a file system from being unmounted in the future).
* WRS emphasized logging.
Some of the details are different (umask as the first function instead of the last), but the highlights are comparable.
Growing up on a (quasi fundamentalist) christian household, daemons were for a long while a very real threat, and my mom would not allow me to watch horror movies, "receive things from strangers", an other procedures to protect us from "inviting the daemons home".
My rational mind leaves no room for such creatures these days, but even so under the right circumstances, sometimes my lizard brain begins to think maybe the Bible (and my mom for that matter) was right :-). Hard to erase some emotive memories from childhood I guess.
A while ago I read this book [1] which is pretty cool, covers the mind mechanisms behind things like the placebo effect, "daemonic possession", alien abductions, mass hysteria, out of body experiences, etc...
[1] https://english.stackexchange.com/questions/39266/what-is-th...
Also got me curious about the C.S. ethymology of the word. According to the venerable Jargon File (which has entries for both "daemon" and "demon"), it is named in honor of one of Maxwell's thought experiments! [1]
Why? On hacker news, you hoped for that?
> Growing up...
Placebo effect, demonic possession, alien abductions, etc? What's going on here? Your comment had nothing to do with the actual post.
http://www.gutenberg.org/files/25929/25929-h/25929-h.html
King James is more famous for the Bible he commissioned. And his treatise on True Law and the divine right of kings. This work of his is somewhat less well-known, I think.
Anyway, it's an amusing read.
https://en.wikipedia.org/wiki/Daemon_(computing)#:~:text=The....
The poem "Dearest creature in creation" is a fun illustration of the differences between spelling and pronunciation.
For example, malloc() may be holding on to a mutex in the parent process (on another thread), so subsequent malloc() calls in the child process will block waiting for the mutex to be released. Closing the file handles may help if this was a kernel mutex, but it may not help if this was a user-space mutex.
In general, fork() without exec() is only safe as the first thing done in a process.
Also, it looks like there is a minor race condition in the implementation: since the original process exit()s immediately after the fork(), control will return to its parent, which may close the session - this could happen before the child had a chance to call setsid() and detach from the parent session.
Furthermore, this bad practice lands one in hot water with library functions, including ironically syslog client libraries, that open and retain file descriptors internally for their own purposes. Yet another case of this was just on Hacker News this week, in fact, at https://news.ycombinator.com/item?id=24329540 .
> service --status-all
$ service --status-all
bash: service: command not foundSo while the command might work for many readers, I don't think it's a good idea to send beginners that way, and its inclusion (without any footnotes or other qualifications) suggests that the author's knowledge is out of date.
I suspect there's not a lot of Win-dev folks on HN.
How is a service started? The SCM launches the specified executable, in the way it's specified in the service's settings and... that's pretty much it.
However, the service is supposed to support a certain protocol of interaction with SCM. First of all, the service must quickly (within half a minute from the start, IIRC) call the WinAPI function StartServiceCtrlDispatcher() on its main thread. That's basically a pre-written main(): it returns only after the service has been stopped. It takes several function pointers: to the ServiceMain where the service proper is supposed to be, and various event handlers (pause/resume/stop requests, system is shutting down, etc). It creates a separate thread to run the ServiceMain on, and then basically loops processing requests/events from the SCM (event handlers are run on the main thread).
That's basically it. Nothing prevents one to write an application that can run both as a service and stand-alone: put your logic in ServiceMain, call StartServiceCtrlDispatcher with it, if it returns ERROR_FAILED_SERVICE_CONTROLLER_CONNECT (that means you're not being launched by the SCM), call ServiceMain by yourself. Ctrl-C handler and "stop the service" handler are easily unified because on Windows, Ctrl-C handler always runs on a different thread. You just need make sure that your ServiceMain function can be safely signaled that it needs to stop from a different thread, but that's what thread-communication primitives are for.
Services are also regularly run on different account especially the ones under "NT AUTHORITY" like "SYSTEM" and "NETWORK SERVICE".
As I recall Visual Studio contains some pretty good templates for writing services with C# but the underlying requirements are abstracted by the .net Framework.
IMO a lot of parts of Windows are a pain to develop on compared to Linux, but creating and managing services are one of the better/smoother parts.
https://docs.microsoft.com/en-us/dotnet/framework/windows-se...
Now depending on what you actually want to do, you have some options:
- Use the Windows Services API to ask Windows to start and manage your process as a system service - this is closest to a SystemD demon
- Create a GUI process with WindowStyle=hidden (this will be part of the current user's session)
- Create a Console process with the DETACHED_PROCESS flag, which should work similarly to the above
- Use one of the CreateProcessAsUser() family of functions to create a process for another user - this should allow the process to run in the background, and allow it to persist even if the current user signs off
In all cases above, you can simply tell CreateProcess* that the child process should not inherit any FDs. You should probably also use the PROC_THREAD_ATTRIBUTE_PARENT_PROCESS flag to spawn this process as the child of some other long-running process, to ensure that the child process is not part of the same Job that the current process may be (usually, when a Job is finished, all processes in that job and any child they spawned, recursively, are killed).
On Linux, it turned out to be surprisingly tricky. Process groups and sessions are not nested, you can easily break out of them and in fact there were some programs we needed to use that insisted on doing daemonization. Thankfully the most important one had a "--foreground" flag but it still was buggy: this program sends SIGTERM to its process group as part of a shutdown — so it kills its parent, too. Amazing. In the end I believe we ended running each worker process as a separate Docker container.
Then there is a dance of waiting (or not waiting? SIGCHILD is truly horrible) on children PIDs to detect the crashes and unexpected hang in the shutdown (the worker process sends "I am done" notification to the parent, but then for some reason doesn't exit). The main process had to be made a sub-reaper to do all of that more or less reliably, and even then there were some strange sightings (signal handling is fun!).
On Windows, we just shoved each worker process into its own unbreakable-from job, and that was it. The main process dies for whatever reasons, its children just disappear. A worker process dies, its children just disappear, without affecting any other worker processes and their children. Detecting termination of the child processes too was a breeze: on Windows, when you spawn a child process you get not only its PID, but also a handle (think "file descriptor") to it. This handle refers exactly to this process, and you can (interruptibly) wait on it, and when the last open descriptor to a process is closed, the process is deleted from the process table. That's why BTW there is no PID 1 that is constantly reaping its children on Windows: each process implicitly has its own handle alway open, so if the parent exits before the child does, nothing bad happens: The child process had 2 open handles on it, now it has 1. When it itself exits, the last handle is dropped, and the slot in the process table is cleaned.
TL;DR: Process management is horrible, use Erlang.