Re: GNU Emacs now runs in foreground

From: Martin \ <et.code_at_ethome.sk>
Date: Wed, 7 Dec 2016 15:56:38 +0100

> On Tue, 6 Dec 2016 10:26:37 -0500
> Steve Litt <slitt_at_troubleshooters.com> wrote:
>
> Thanks Martin,
>
> Could you please show me your run scripts for tmux, screen and mpd?
> These are the three I could see myself using in this manner.
>
> SteveT
>
> Steve Litt
> November 2016 featured book: Quit Joblessness: Start Your Own Business
> http://www.troubleshooters.com/startbiz
>

Well, ... hmm, ... okay, ... but I am one of those people doing everything my
way despite what others tell me. I am sometimes embarassed about it as well
(still), but am slowly learning to not give a damn.

I wanted to avoid complete disclosure, as I think one of my things is not
ready yet, but here is my infodumpy giant wall of text. I hope, I won't regret
it.

Currently I "share" my home dir with zfs send, between Void Linux notebook and
FreeBSD workstation. To ease my exploratory behaviour, for now, I am using dash
(on Void) and /bin/sh which are compatible for these kinds of things
(./run, ./finish). Workstation part is not used often, so not everything works
there yet.

I also have few FreeBSD servers with s6 only supervisions. Sometimes I use
execline but not always ... yet.

On my presonal box "user level" s6 /services subtrees are in `.config/s6/host`
for "host" level user services, (outside of xorg "sessions") and in
`.config/s6/xsession-0` is where default xorg session lives.

> - mpd - the music player daemon

I am bit weird, so I run mpd as my own user as my music library is in my
/home. As I am sole user of the machine, I like it better that way.
Mpd requires user to be in auxiliary audio group for ALSA access.
I spawn whole s6 "host" tree with that group, with s6-applyuidgid, as I was
hinted by supervision folks on irc. I am still working on it though.
Runscript:
+--
|% cat .config/s6/host/mpd/run
+--
|#!/bin/sh
|exec mpd --no-daemon /usr/home/eto/.config/mpd/mpd.conf
+--

MPD is configured to bind to explicit socket
+--
|% cat .config/mpd/mpd.conf | grep bind
+--
|bind_to_address "~/.config/mpd/run/socket"
+--

To be 100% sure ncmpcpp or X clients can find the socket I export it to X
session:
+--
|% cat .config/s6/xsession-0/.s6-svscan/env/MPD_HOST
+--
|/usr/home/eto/.config/mpd/run/socket
+--

To be sure I can control(!) music with ncmpcpp on raw VT terminal, I modified
Void's agetty runit script to load given variable (maybe not the brightest
decision):
+--
|% cat /etc/runit/runsvdir/default/mybox-agetty-tty2/env/MPD_HOST
+--
|/usr/home/eto/.config/mpd/run/socket
+--

agetty also needed addition of `-o "-p -- \u"` switch to preserve environment.
One also might use pam_env, but I dislike pam.

Final result: uninterrupted music until I shut down computer or mpd service
itself, no matter whether X runs or not, or crashes (happens only when I am
messing with it), thus yeeeey!

> On Tue, 6 Dec 2016 23:31:40 +0000
> Jonathan de Boyne Pollard <J.deBoynePollard-newsgroups_at_NTLWorld.com> wrote:
>
> Martin "eto" Misuth:
> > - rxvt-unicode - uberterminal
> > - this thing can operate [...] daemon, when single process hosts all
> > your terminals
> > - benefits are [...]
>
> Drawbacks are that it doesn't understand receiving the listening socket
> as an already-open file descriptor, and by default it places the socket
> in $HOME/.urxvt/ rather than in /run/user/$USER/urxvt/ .

I personally am not so "hot" about this listening socket passing stuffs.
Don't get me wrong, I am learning to do it myself in my crappy attempts,
from scripting language, but I see it as important only in thightly coupled
swarms of cooperating processes.

I also see value in "piercing" something like FreeBSD jail and passing
socket inside it - someting I would like to be able to do with vanilla nginx at
some point. Inside jail unix sockets are just fine to fan out data flows into
fastcgi handlers, database servers and whatnot. It is intereseting bcause that
way jail doesn't even need IP. Anybody wreaking havoc in it cannot reach
network...

However for normal "enduser" - ability to control and pass connection endpoints
between various process environments - is sufficient and much better design.
That way one can control access with unix permissons and whatnot. No need to
pack info about FD into env var and pass it in process state.

Thus env var for rxvt clients:
+--
|% cat .config/s6/xsession-0/.s6-svscan/env/RXVT_SOCKET
+--
|/usr/home/eto/.config/urxvt/run/socket
+--

And env var for rxvt server:
+--
|% cat .config/s6/host/urxvtd/env/RXVT_SOCKET
+--
|/usr/home/eto/.config/urxvt/run/socket
+--

As you see, terminal daemon currently runs "outside" of x session.

It was experiment to see whether it kills all spawned "shell trees" when x goes
away. Which it of course does. Maybe Mr Schmorp would be willing to implement
feature to freeze shell instances in such cases? Who knows.

Now we get to most embarassing part:
  - after reading some info about proper "zombie reaping" on various djb
    inspired sites
    - including s6's one
  - observing behaviour of reparenting under init for thousands of times in htop
  - FreeBSD getting DragonflyBSD inspired "subreaper"
    - to match Linux "subreaper" functionality
    - but it being BSDs ending with considerably higher quality interfaces
  - and having some salty feelies about how FreeBSD jail(8) organizes
    processes...

... I decided I will give it try and attempted "small" utility to use this
"subreaper thing" for "better" service implementation.

This tool has hard skalibs dependency, and is kinda kitchensink by now,
but works pretty well for me, and is not liked by Mr skarnet at all
(described as foolish).

By that sentence I want to stress there is no endorsement at all,
quite the contrary, yet my stupid questions are tolerated, and I
want to show how awesome "live and let live" community
supervision folks are.
 
Tool is probably somewhere between late alpha perhaps even stabler beta.

Because it is tightly coupled to s6' skalibs and I go by nickname ET among
firends, I named it ets6-reaper.

If this is confusing name, I would be grateful for any better prefix
suggestions. I want to convey to readers it depends hard on skalibs but it's
from silly me.

Point of tool is simple: it always runs marking itself as "subreaper", thus
any descendants who lose parent, that was running under it, will get reparented
(and their attached process subtrees as well) under it's process.

It is kinda a "hack" but I don't see it as "that bad".
It falls somewhere along the lines of s6-pause or void-runit/pause, from Mr
Christian Neukirchen.

Once "main", the important and original, child exits, tool tries to term and
then kill all remaining descendants.

Unless it aborts unexpectedly (which haven't happened to me so far), it is
pretty capable of being "the leader" that will not allow any descendants to get
reparented under PID1. If it itself is "led" by s6-supervise or runsv, it has
thus ability to terminate all the lingering processes spawned by service.

I did this to avoid use of cgroups (which are not on FreeBSD), and to preserve
process swarm hierarchy. top, ps with "forest" option and htop, all now capture
and display service process hirarchies quite clearly this way (runit example):
     │
root └─ runsv mybox-agetty-tty2
root └─ ets6-reaper[5s,1s]: tty2 - running - main[3073:login -- eto]
root └─ login -- eto
eto └─ zsh

I definately plan to share it on github at some point, but I am not confident
enough yet. I think Mr Jonathan de Boyne Pollard might be cooking, or even
already has, something similar in nosh. And few other people expressed interest
in these "subreaper" facilities and, I belive, are experimenting with them.

Sidenote: at some point I was interested in digging out whether systemd had
"subreapers" at it's disposal, and why it didn't use them (instead it groups
processes by cgroups that are completely orthogonal to traditional process
management methods), but I concluded it's unimportant and gave up that
investigation.

So after this lenghty infodump, this line in urxvtd run script should
(hopefully) make perfect sense:
+--
|% cat .config/s6/host/urxvtd/run
+--
|#!/bin/sh
|
|exec /bins6/ets6-reaper \
| -n 'urxvtd' \
| -N "eto's urxvt deamon" \
| 2 2 \
| /bins6/s6-envdir ./env /usr/bin/urxvtd -q
+--

It forces all shell children to follow reaper and term together even when urxvtd
crashes or service is torn down (like when I spawned something daemonising and
forgot). I am still hitting some corner cases there, though.

> - super famous tmux - terminal multiplexer

Getting tmux "supervised" was bit tricky as it double forks the daemon
if not running, and is thus is "escaping under init" under normal conditions.

Instead of Linux, this is on FreeBSD system, and it is used for cca 4 devs to
host several jails for each to support their development adventures.

By "abusing reaper" hack with "ignore main child exit" (-xi) option, it makes
daemon-less tmux client double fork into tmux-daemon, which gets reparented
under reaper, and as reaper is capable of relaying term signal to
descendants, it makes main `s6-svc -d /services/tmux-eto` semantics
work. As reaper runs as root (because of parent s6-supervise),
it also has capability to termiante all the trees user might have left
running, when sysadmin issues service down command:

+--
|% cat /jails.data/devboxes/services/tmux-eto/run
+--
|#!/usr/local/bin/execlineb -P
|
|/usr/local/bin/export HOME /usr/home/eto
|
|ets6-reaper
| -x i
| -u eto:wheel
| -n "tmux-eto"
| -N "etov tmux na devboxes"
| 10 5
| /usr/local/bin/tmux
| new-session -d
| -c /ucr/home/eto
| -s devcontrol
| -n main
+--

There is "problem window" as well. When sevice is down, and somebody starts tmux
on their ssh connection, it will double fork and do it's magic thing. Because
this is in jail with another reaper like thing leading it, it still stitches
process tree together though (so when turning off jail, we get proper
"cleanup"). But to avoid this corner case, when messing with this specific jail,
I just disable ssh service as well, and then it's no problem.

It would be great if tmux project allowed to spawn raw user level daemon by
explicit command, but I have not found the way how to do it vanilla. There is
tmux -C option for "control mode", but I vaguely remember it didn't work well
for me that way (I think it still spawned double forked daemon anyway).

This already works very well for us. If somebody forgets something running,
which happens a lot (tailing some log or something) especially with convenient
things like tmux, I am able to tear their whole tree down without wearing rambo
hat and hunt and peck their processes by user id.

This is roughly the git of it.

  eto
Received on Wed Dec 07 2016 - 14:56:38 UTC

This archive was generated by hypermail 2.3.0 : Sun May 09 2021 - 19:44:19 UTC