Fwd: [PATCH] runit-2.1.2 svlogd: never prune the in-progress .u

2015-04-29 Thread Mike Pomraning
When rotating, svlogd treats unfinished .u files and saved .s files alike,
deleting the oldest it finds.

However, if the system clock has stepped backward, the in-progress .u file,
which is input for the post-rotation processor, may appear older than any
rotated .s files.  In that case, svlogd becomes wholly unresponsive, stuck
in a pathological loop trying to process a file that doesn't exist, and
must be SIGKILLed.

The below patch appears to address the issue for me, and is an improvement
over my previous attempt to simply ignore (rather than loop forever around)
the ENOENT.  svlogd will still rotate any older (interrupted) .u files it
finds, as normal, but it will leave the about-to-be-processed .u untouched.

Gerit, please consider this issue for the next release of runit.  It's
acceptable IMO that funny clocks might degrade time-based log rotation,
perhaps even losing data, but not that a clock jump would unrecoverably
hang the service.

-Mike

--- src/svlogd.c.orig 2013-02-26 14:15:45.886549000 -0600
+++ src/svlogd.c 2015-04-28 23:50:41.116613675 -0500
@@ -222,8 +222,10 @@ void rmoldest(struct logdir *ld) {
   DIR *d;
   direntry *f;
   char oldest[FMT_PTIME];
+  int will_process;
   int n =0;

+  will_process = (ld->fnsave[26] == 'u');
   oldest[0] ='A'; oldest[1] =oldest[27] =0;
   while (! (d =opendir(".")))
 pause2("unable to open directory, want rotate", ld->name);
@@ -235,8 +237,12 @@ void rmoldest(struct logdir *ld) {
   warn2("unable to unlink processor leftover", f->d_name);
   }
   else {
-++n;
-if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27,
f->d_name);
+++n; /* count .s and .u files ... */
+
+if (str_diff(f->d_name, oldest) < 0)
+   /* ... but don't unlink our pending .u if the clock is funny */
+  if (! (will_process && (str_diff(ld->fnsave, f->d_name) == 0)))
+byte_copy(oldest, 27, f->d_name);
   }
   errno =0;
 }


Re: Thoughts on "First Class Services"

2015-04-29 Thread Avery Payne
Note: this re-post is due to an error I made earlier today.  I've gutted 
out a bunch of stuff as well.  My apologies for the duplication.


On 4/28/2015 11:34 AM, Laurent Bercot wrote:


I'm also interested in Avery's experience with dependency handling.


Hm.  Today isn't the best day to write this (having been up since 4am) 
but I'll try to digest all the little bits and pieces into something.  
Here we go...


First, I will qualify a few things.  The project's scope is, compared to 
a lot of the discussion on the mailing list, very narrow.  There are 
several goals but the primary thrust of the project is to create a 
generic, universal set of service definitions that could be plugged into 
many init, distribution, and supervision framework arrangements. That's 
a tall order in itself, but there are ways around a lot of this.  So 
while the next three paragraphs are off-topic, they are there to address 
those three concerns mentioned.


With regard to init work, I don't touch it.  Trying to describe a proper 
init sequence is already beyond the scope of the project. I'm leaving 
that to other implementers.


With regard to distributions, well, I'm trying to make it as generic as 
possible.  Development is done on a Debian 7 box but I have made efforts 
to avoid any Debian-isms in the actual project itself.  In theory, you 
should be able to use the scripts on any distribution.


With regard to the supervision programs used, the difference in command 
names have been abstracted away.  I'm not entirely wild about how it is 
currently done, but creating definitions is a higher priority than 
revisiting this at the moment.  In the future, I will probably 
restructure it.


~ ~ ~ ~ ~ ~ ~ ~

What
---
The dependency handling in supervision-scripts is meant to be used in 
installations that don't have access to it.  Put another way, it's a 
"Poor Man's Solution" to the problem and functions as a convenience.  
The feature is turned off by default, and this will cause any service 
definition that requires other services to run-loop repeatedly until 
someone starts them manually.  This could be said to be the default 
behavior of most installations that don't have dependency handling, so 
I'm not introducing a disruptive behavior with this feature.


Why
---
I could have hard-coded many of the dependencies into the various run 
scripts, but this would have created a number of problems for other areas.


1. Hard-coding prevents switching from shell to execline in the future, 
by necessitating a re-write.  There will be an estimated 1,000+ scripts 
when the project is complete, so this is a major concern.


2. We are already using the filesystem as an ad-hoc database, so it 
makes sense to continue with this concept.  The dependencies should be 
stored on the filesystem and not inside of the script.


With this in mind, I picked sv/(service)/needs as a directory to hold 
the definitions to be used.  Because I can't envision what every init 
and future dependency management framework would look like, I'll simply 
make it as generic as I can, leaving things as open as possible to 
additional changes.A side note: it is by fortuitous circumstance 
that anopa uses a ./needs directory that has the same functionality and 
behavior.  I use soft links "just because".  Anopa uses named files.  
The net effect is the same.


Each dependency is simply a named soft link that points to a service 
that needs to be started, typically something like 
"sv/(service)/needs/foobar points to /service/foobar".  In this case, a 
soft link is made with the name of the service, pointing to the service 
definition in /service.  This also allows me to ensure that the 
dependency is actually available, and not just assume that it is there.


A single rule determines what goes into ./needs, "you can only have the 
names of other services that are explicitly needed".  You can say "foo 
needs baz" and "baz needs bar" but NEVER would you say "foo needs baz, 
foo needs bar".  This is intentional because it's not the job of the 
starting service to handle the entire chain.  It simplifies the list of 
dependencies because a service will only worry about its immediate 
needs, and not the needs of dependent services it launches.  It also has 
the desirable property of making dependency chains self-organizing, 
which is an important decision with hundreds of services having 
potentially hundreds of dependencies.   Setup is straightforward and you 
can easily extend a service need by adding one soft link to the new 
dependency.  This also fits with my current use of a single launch 
script; I don't have to change the script, just the parameters that the 
script uses.  The new soft link becomes just another parameter.  You 
could call this "peer-level dependency resolution" if you like.



How
---
Enabling this behavior requires that you set sv/.env/NEEDS_ENABLED to 
the single character "1".   It is normally set to "0".  With the setting 
disabled (