<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, May 16, 2014 at 9:38 AM, Lennart Poettering <span dir="ltr"><<a href="mailto:lennart@poettering.net" target="_blank">lennart@poettering.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">On Thu, 15.05.14 20:57, Brandon Black (<a href="mailto:blblack@gmail.com">blblack@gmail.com</a>) wrote:<br>
<br>
> On Thu, May 15, 2014 at 6:40 PM, Lennart Poettering<br>
> <<a href="mailto:lennart@poettering.net">lennart@poettering.net</a>>wrote:<br>
> ><br>
> > But again, it's generally not a good idea to keep file locks for a<br>
> > longer period of time, much as with mutexes... You don't want to make<br>
> > other apps which try to get an atomic view on the file hang for long.<br>
><br>
> If they don't want to hang, they don't have to. There are nonblocking<br>
> calls to check for a conflicting advisory fcntl() lock. The pidfile should<br>
> be private from random software anyways, other than the daemon itself and<br>
> perhaps whatever tools or init system are managing start/stop.<br>
<br>
</div>Note that other programs might read your PID files too, for example<br>
systemd. And systemd won't take a lock on it (we don't want to make PID1<br>
deadlock...).</blockquote><div><br></div><div>I guess whether systemd or another init system needs to read the PID file is a design question, and my daemon design for this stuff tends to be "different". At least in my model, there's no reason for a normal init system to need to read the pidfile - it's only used for exclusivity between multiple instances of the same daemon to avoid races, and the fcntl() lock information is used by status/stop/restart -like commands to identify a running daemon without races or process misidentification. Exactly one daemon holds the fcntl writelock on the designated pidfile pathname, and its PID is retrievable by reading the lock, which is released on daemon shutdown or death. And again, under systemd this can be made to work with sd_notify of MAINPID. </div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> Hence you need to make sure you write those files<br>
atomically anyway, and you cannot use locks for that, you have to use<br>
atomic renames... And if you do that, the locks become pretty useless...<br>
<div class=""></div></blockquote><div><br></div><div>Atomic renames (+ fsync!) get you a pidfile that's always readable by other processes, but what they don't get you is solving the problem of races between multiple instances of the daemon itself. The data contained within won't be reliable in a lot of real-world corner cases. What happens when someone issues a start command while another start command was still executing? Or a start while a stop was still executing, etc? Almost every scheme for pidfile management that tries to solve all the issues surrounding it (guaranteeing a lack of two conflicting instances of the same daemon, not losing track of a daemon by letting another instance overwrite its pidfile while it's still running, "stop" commands never try to mess with an unrelated process, and that status commands aren't confused by them, etc) that I've ever seen has serious flaws. I still think the fcntl() method is the least-flawed of reasonably-portable methods.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">
> IMHO, the method of taking an fcntl() writelock on a private pidfile<br>
> is one<br>
<br>
</div>Also not that fnctl() (i.e. POSIX) locks are particularly broken<br>
actually, as they are removed whenever close() is invoked by your<br>
process on *any* fds to the file, even if you opened a completely<br>
independent fd. POSIX locks are excessively difficult to use properly,<br>
and in particular if you keep them over longer times...</blockquote><div><br></div><div>Lots of things break if you, as the application developer, can't keep track of where in your code you're messing a critical file like an exclusively-locked pidfile. Don't open other fds to the critical pidfile owned by your daemonization code, problem solved? Yes, POSIX locks are difficult to use properly. Almost everything about *nix daemonization is difficult to do properly (isn't that one of the many things systemd is trying to solve, at least for the Linux case?).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">
> of the most reliable methods around for this stuff in the general case<br>
> outside of systemd-land. AFAIK it's just about the only reliable way that<br>
> doesn't have inherent races or accidentally kill (or be DoS'd by) unrelated<br>
> processes in corner cases. You don't even have to read the contents<br>
> of the<br>
<br>
</div>Umm, no... POSIX locks are not NFS safe, and vulnerable, and really<br>
broken. They are a portability nightmare, and you claim to use them<br>
because of portability.... Also see this:<br>
<br>
<a href="http://0pointer.de/blog/projects/locking.html" target="_blank">http://0pointer.de/blog/projects/locking.html</a></blockquote><div><br></div><div>Who puts daemon pidfiles on NFS (or at the very least, who would expect them to grant lock-based daemon exclusivity across NFS)? That's a whole separate problem. They're portable enough that they work for me on Linux (systemd or not), *BSD, and MacOS. I'm not trying to port to ancient systems here.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Anyway, this is not the place for discussing the brokeness of Linux file<br>
locking, so let's end this here...</blockquote><div><br></div><div>IMHO, given that systemd replaces the init infrastructure for managing long-running daemons, and given that it places a lot of practical and conceptual limitations on what a daemon is and how it is managed versus a traditional semi-portable *nixy way of doing things due to making very large changes in this area, I think discussion of best practices for portable daemons and how to best integrate those practices to accomplish the same goals under systemd is *very* germane to this list.</div>
</div></div></div>