Re: On the feasibility of a shell that includes execline features

From: Laurent Bercot <ska-supervision_at_skarnet.org>
Date: Mon, 22 Aug 2016 22:13:38 +0200

On 21/08/2016 17:00, Casper Ti. Vector wrote:
> In [1], I (probably after many other people with similar ideas) came up
> with the idea of a "language that somehow combines execline-like
> chainloading and shell-like sequential execution".

  I understand how the idea is tempting; and if someone wants to try their
hand at writing something like that, it's certainly an interesting goal.

  However, I think you'd find the benefits aren't quite what they seem
to be at first sight. You'd probably end up with something that is more
complex than the sum of a shell and execline. And the reason for that is
the fundamental difference between a persistent process and one that is
not.

  There is an extremely measurable benefit in writing chain-loading programs,
as far as maintainability is concerned: you do not need to bother with
data structure cleanup at all. You can be incredibly careless with your data,
have pointers into the stack, let entire trees leak - all this doesn't
matter because you're going to execve() right away and the kernel is going
to clean up everything for you. You're not going to have dangling pointers
and you're not going to leak memory. If you have sensitive data, it's gone,
too. (At least it should be. I hope security-conscious kernels actually
wipe the allocated physical pages before giving them to other processes.)

  I use this property a lot, in particular to avoid pulling in malloc()
when I can store all my data into a stack that would be popped in a
persistent program, but won't be here because execve(). This is a really big
factor in making C programs very simple to write and maintain, and also
very resilient - and very efficient. execve() may be slow, but it's powerful,
and the kernel is a wonderful janitor.

  Look at
http://git.skarnet.org/cgi-bin/cgit.cgi/execline/tree/src/execline/export.c :
it doesn't get any simpler than that.

  In a persistent process, you can't afford to do that: you have to keep a
clean accounting of your resources. First, you initialize your runtime,
which is in itself some unavoidable boilerplate, even if your task is
really simple (whereas a launcher such as execlineb doesn't have a runtime
to initialize). Then you loop; for every iteration of the loop, you do some
task that needs to communicate with other tasks; so you allocate resources
whose lifetime may exceed the lifetime of the task. So you can't use a
stack, and you can't yolo allocations in the wild - you have to perform
accurate resource management. Which is what people hate about C, and I
can't blame them.

  Busybox does that. It's painful. It's one of the reasons why toybox is
smaller.

  So, yes. In a shell you have no choice: you need to be persistent. And so,
if you implement "chain-loading" functions as shell builtins, you may
save a few execs, but the code for your builtins will be significantly more
complex than what they are for instance in execline, because you'll be
duplicating the work of the kernel. No matter how well-designed the "rc"
family of shells is, it's unavoidable and unsatisfying overhead.

-- 
  Laurent
Received on Mon Aug 22 2016 - 20:13:38 UTC

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