[comp.arch] Spawn is impossible to define

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (07/23/90)

In article <XRS4OLF@xds13.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>> In spite of my request to actually show a "rational definition of spawn",
>> no one has ever shown it.

>OK, what capabilities in the child process need to be modified by the parent
>process, but can not be non-destructively changed by the parent.

Thanks for showing the inherent complexity and impossibility of defining
spawn call, again.

>In UNIX the most important parts are current directory, user ID, open files,
>and environment variables. Environment variables are already explicitly passed
>by exec*e.

HOW DO YOU THINK ABOUT SIGNALS?

>Open files can be handled by passing a vector of fds to be stuck into the
>child's file descriptord.

It reminds me of a AEGIS (yes, I know of other OSs). It was real pain
to use that OS.

						Masataka Ohta

peter@ficc.ferranti.com (Peter da Silva) (07/23/90)

In article <5929@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
> Thanks for showing the inherent complexity and impossibility of defining
> spawn call, again.

Two more arguments than "exec" is too much complexity?

> HOW DO YOU THINK ABOUT SIGNALS?

Signals can be reliably saved and restored, so they can continue to be
inherited across spawn as they are now inherited across fork and exec.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (07/24/90)

In article <E5V4K+F@xds13.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>In article <5929@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
>> Thanks for showing the inherent complexity and impossibility of defining
>> spawn call, again.

>Two more arguments than "exec" is too much complexity?

Two more arguments is not complex.

>Signals can be reliably saved and restored, so they can continue to be
>inherited across spawn as they are now inherited across fork and exec.

If a parent process want to catch some signal (whose default action
is termination) and a child process want to ignore it, how can it
be done? Parent process should not discard delivered signal, of
course.

BTW, signal is not an only thing you miss.

						Masataka Ohta

peter@ficc.ferranti.com (peter da silva) (07/24/90)

> >Signals can be reliably saved and restored, so they can continue to be
> >inherited across spawn as they are now inherited across fork and exec.

> If a parent process want to catch some signal (whose default action
> is termination) and a child process want to ignore it, how can it
> be done?

Good point. Of course one more race condition in signals is just noise
compared to the mess they are already in. I'm not familiar with the
semantics of Berkeley's reliable signals, but I suspect that something
could be done with them to resolve this.

> BTW, signal is not an only thing you miss.

Well, enlighten me.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

johnl@esegue.segue.boston.ma.us (John R. Levine) (07/25/90)

In article <XYV4D8A@ggpc2.ferranti.com> peter@ficc.ferranti.com (peter da silva) writes:
>Signals can be reliably saved and restored, so they can continue to be
>inherited across spawn as they are now inherited across fork and exec.

Nope.  Assume that the parent is ignoring quits, while the child accepts
them, as is typically the case when running something from a top-level shell.
If the parent enables quits around the spawn() so that the enabled status is
inherited by the child, you run the risk that the user will hit quit at an
inconvenient time and will blow the parent away, too.  To fix this particular
nit either you have to pass a signal status vector to your spawn() call or
else crud up the signal system with a state that means
accept-if-inherited-in-subprocess-but-not-here.  Ugh.

When I first thought about this problem, I also thought that it should be
possible to come up with a spawn call that would obviate fork/exec.  Now I'm
convinced that it can't be done.  Enumerating all of the bits of the
user-visible context of a process is extremely hard, and of course every time
you add a new system call or feature, you porentially add more context.  It
seems to me that if you want to add spawn, you have a small set of options:

-- Have spawn point to a piece of setup code in the parent process that is
executed in the child process' context to set stuff up.  This is what vfork
is supposed to do.

-- Redo every call that affects process context so that it takes as an
extra argument the PID of the process to change, defaulting to one's own
process.  Then spawn needs only one option, to freeze the child until the
parent releases it after doing all the context changing.  Details of what
process is allowed to change the context of what other processes are left
for the reader, but are clearly a major can of worms if you have any
pretense of security (what if the child is set-uid to root?)

-- Implement a limited spawn() while leaving fork/exec for the hard cases,
but use spawn for the common cases to make things fast.  The problem here is
that the most common place for fork/exec is from a shell or shell procedure,
and shells both tend to be pretty small, and to do considerable munging of
file descriptors and signals after the fork.  Thus, the most common case also
happens to be one of the cheapest now and to be fairly obnoxious to handle
with spawn().

-- Give up and stick with fork and exec.  That's my choice.
-- 
John R. Levine, Segue Software, POB 349, Cambridge MA 02238, +1 617 864 9650
johnl@esegue.segue.boston.ma.us, {ima|lotus|spdcc}!esegue!johnl
Marlon Brando and Doris Day were born on the same day.

peter@ficc.ferranti.com (Peter da Silva) (07/25/90)

In article <1990Jul24.194313.3258@esegue.segue.boston.ma.us> johnl@esegue.segue.boston.ma.us (John R. Levine) writes:
> In article <XYV4D8A@ggpc2.ferranti.com> peter@ficc.ferranti.com (peter da silva) writes:
> >Signals can be reliably saved and restored, so they can continue to be
> >inherited across spawn as they are now inherited across fork and exec.

> Nope.  Assume that the parent is ignoring quits, while the child accepts
> them, as is typically the case when running something from a top-level shell.

Well that case can be dealt with (parent catches and discards interrupts
around the spawn call), but the reverse case creates a race condition. This
is not good, but it's also true that UNIX signals are *full* of such
race conditions (hit ^C fast enough and you can blow away the shell).
What is needed is a "defer signals" state, along with "default, catch,
and ignore". This would solve this race condition, and also the one where
the signal handler gets interrupted before resetting the signal.

> Enumerating all of the bits of the
> user-visible context of a process is extremely hard, and of course every time
> you add a new system call or feature, you porentially add more context.

But you have to do this anyway to allow for proper use of fork/exec. Better
to make *any* change in process context reversible, then set things up,
spawn, and reset. Currently the only non-reversible inherited changes are open
files and current directory. And, I guess, chroot().

> -- Have spawn point to a piece of setup code in the parent process that is
> executed in the child process' context to set stuff up.  This is what vfork
> is supposed to do.

And I agree that vfork is a good idea, besides being more convenient than
spawn. I just don't see that spawn is really any more complex than, say,
select().

> -- Give up and stick with fork and exec.  That's my choice.

You forgot:

-- Make any change in the process context reversible. Which is a damned
useful capability anyway.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (07/30/90)

In article <=VW4JSA@xds13.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>Well that case can be dealt with (parent catches and discards interrupts
>around the spawn call), but the reverse case creates a race condition.

Can be. But, it is too tricky for Average programmers.

>This
>is not good, but it's also true that UNIX signals are *full* of such
>race conditions (hit ^C fast enough and you can blow away the shell).

That is untrue for BSD UNIX.

>What is needed is a "defer signals" state, along with "default, catch,
>and ignore". This would solve this race condition, and also the one where
>the signal handler gets interrupted before resetting the signal.

OK. You want to intruduce a new (to SysV) state of a process. Then, how
can you set the defer/don't-defer state of a child process with spawn?

						Masataka Ohta

peter@ficc.ferranti.com (Peter da Silva) (07/31/90)

In article <5962@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
> In article <=VW4JSA@xds13.ferranti.com>
> 	peter@ficc.ferranti.com (Peter da Silva) writes:
> >Well that case can be dealt with (parent catches and discards interrupts
> >around the spawn call), but the reverse case creates a race condition.

> Can be. But, it is too tricky for Average programmers.

So, from my own observation of such code culled from the net, is signal
handling and fork/exec in any case.

> >This
> >is not good, but it's also true that UNIX signals are *full* of such
> >race conditions (hit ^C fast enough and you can blow away the shell).

> That is untrue for BSD UNIX.

That's using BSD's "reliable signales", which are an extension to standard
UNIX signals. I'm sure that they also have the ability to solve the problem
you originally posited.

> >What is needed is a "defer signals" state, along with "default, catch,
> >and ignore". This would solve this race condition, and also the one where
> >the signal handler gets interrupted before resetting the signal.

> OK. You want to intruduce a new (to SysV) state of a process.

No, of a signal. A state that is also useful in that it solves the race
conditions inherent in generic UNIX signals without adding the unwanted
complexity of BSD's reliable signals system. KISS.

> Then, how
> can you set the defer/don't-defer state of a child process with spawn?

You don't, because it's not meaningful any more than setting the catch/
don't catch state of a signal. Neither is useful without a signal handler,
and that signal handler is sitting back in the parent process unavailable
to the newly spawned/execed child.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (08/01/90)

In article <OP-4G62@xds13.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>> >Well that case can be dealt with (parent catches and discards interrupts
>> >around the spawn call), but the reverse case creates a race condition.

>> Can be. But, it is too tricky for Average programmers.

>So, from my own observation of such code culled from the net, is signal
>handling and fork/exec in any case.

You seems to be thinking quality of average programmers very low.
Then, surely, broken spawn is as good as vfork-exec to them, because
they can use neither of them.

>> >This
>> >is not good, but it's also true that UNIX signals are *full* of such
>> >race conditions (hit ^C fast enough and you can blow away the shell).
>
>> That is untrue for BSD UNIX.
>
>That's using BSD's "reliable signales", which are an extension to standard
>UNIX signals.

Then, you don't know BSD's reliable signal. You don't have to use extension
such as sigvec() explicitely. In BSD, standard UNIX system call signal()
itself is reliable.

>I'm sure that they also have the ability to solve the problem
>you originally posited.

But you are wrong. The problem is still impossible to solve.

You shouldn't be sure about such a complex thing without actually
solving it.

>> OK. You want to intruduce a new (to SysV) state of a process.
>
>No, of a signal. A state that is also useful in that it solves the race
>conditions inherent in generic UNIX signals without adding the unwanted
>complexity of BSD's reliable signals system. KISS.

And you can't still solve the case I mentioned.

>> Then, how
>> can you set the defer/don't-defer state of a child process with spawn?

>You don't, because it's not meaningful any more than setting the catch/
>don't catch state of a signal. Neither is useful without a signal handler,

Catch/don't-catch? Why did you change wording? Are you trying to confuse me?
Ignoring of signals and defering of signals are different things.

We are talking about a signal state of defer/don't-defer. The state is
meaningful even without signal handler, because, during the state of
defer, we can setup an appropriate signal handler.

So, defer/don't-defer state IS meaningful without signal handlers.

						Masataka Ohta

peter@ficc.ferranti.com (Peter da Silva) (08/01/90)

In article <5971@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
> >No, of a signal. A state that is also useful in that it solves the race
> >conditions inherent in generic UNIX signals without adding the unwanted
> >complexity of BSD's reliable signals system. KISS.

> And you can't still solve the case I mentioned.

Wrong on two counts. Setting a deferred signal (inherited as caught) solves
the case *I* mentioned. The one *you* came up with can be solved with normal
UNIX signals, and I explained how. If you can't remember a message I posted
only a few days ago I'm not going to bother repeating it.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (08/02/90)

In article <.D+4Y53@ggpc2.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>Wrong on two counts. Setting a deferred signal (inherited as caught) solves
>the case *I* mentioned. The one *you* came up with can be solved with normal
>UNIX signals, and I explained how. If you can't remember a message I posted
>only a few days ago I'm not going to bother repeating it.

You once (and still) failed to show a definition of spawn.

Then, this time, you failed to show code sequence of proper signal
inheritance.

Now, you should realize what you are trying to do is impossible.

If there is any other person who still thinks spawn is a nice idea,
show me your definition of spawn.

						Masataka Ohta

peter@ficc.ferranti.com (Peter da Silva) (08/02/90)

In article <5978@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
> In article <.D+4Y53@ggpc2.ferranti.com>
> 	peter@ficc.ferranti.com (Peter da Silva) writes:
> >Wrong on two counts. Setting a deferred signal (inherited as caught) solves
> >the case *I* mentioned. The one *you* came up with can be solved with normal
> >UNIX signals, and I explained how. If you can't remember a message I posted
> >only a few days ago I'm not going to bother repeating it.

> You once (and still) failed to show a definition of spawn.

A. That's not what you were asking in the message I was following up to.

B. I already did.

	spawn*(fdset, *)

Where * is replaced by the equivalents from exec*. The "fdset" is no
uglier in spawn than select. By making every other change to the process
image reversible (which is in itself a very useful feature) no other
arguments are needed.

> Then, this time, you failed to show code sequence of proper signal
> inheritance.

What, to have the signal SIG_DFL in the child and SIG_IGN in the parent?
You call "signal(dummy, SIGwhatever)" where dummy() just resets the signal
and ignores it, then call spawn. I explained that three messages back,
now. I'm not responsible for your memory... perhaps you should save these
articles.

> Now, you should realize what you are trying to do is impossible.

No, just difficult. Like many things in small operating systems running
on hardware with no MMU, you have to work harder to accomplish the same
thing. I'm not prepared to double the price of a product just so you can
fit a full UNIX kernel in the PROMs.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

mohta@necom830.cc.titech.ac.jp (Masataka Ohta) (08/06/90)

So far, no one else is interested in spawn. That's fine.

Perhaps, this is my last post on the impossibility of spawn.
I am also bored.

In article <Q8.4+CB@xds13.ferranti.com>
	peter@ficc.ferranti.com (Peter da Silva) writes:

>> You once (and still) failed to show a definition of spawn.

>B. I already did.

But it won't work.

>> Then, this time, you failed to show code sequence of proper signal
>> inheritance.
>
>What, to have the signal SIG_DFL in the child and SIG_IGN in the parent?

No. As I pointed out, and you admitted, it's reverse is the case you
can't handle.

>> Now, you should realize what you are trying to do is impossible.
>
>No, just difficult. Like many things in small operating systems running
>on hardware with no MMU, you have to work harder to accomplish the same
>thing.

We have been talking about UNIX. I don't want to continue the meaningless
discussion by enlarging domain.

>I'm not prepared to double the price of a product just so you can
>fit a full UNIX kernel in the PROMs.

You can do whatever you want with your own OS. I can't stop it.

						Masataka Ohta

dab@myrias.com (Danny Boulet) (08/07/90)

In article <Q8.4+CB@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>What, to have the signal SIG_DFL in the child and SIG_IGN in the parent?
>You call "signal(dummy, SIGwhatever)" where dummy() just resets the signal
>and ignores it, then call spawn. I explained that three messages back,
>now. I'm not responsible for your memory... perhaps you should save these
>articles.

The problem with this approach is that the parent may not want to ever run
with the signal set to SIG_DFL.  For example, if the parent wants to run with
^C always disabled but wants to start a child with ^C enabled, the scheme
you propose creates a window for the ^C to sneak through (not a very big window
but I'm constantly amazed at how good interrupts are at finding windows).

>Peter da Silva.   `-_-'
>+1 713 274 5180.   'U`
><peter@ficc.ferranti.com>

peter@ficc.ferranti.com (Peter da Silva) (08/07/90)

In article <5986@titcce.cc.titech.ac.jp> mohta@necom830.cc.titech.ac.jp (Masataka Ohta) writes:
> No. As I pointed out, and you admitted, it's reverse is the case you
> can't handle.

You didn't point out anything. *I* pointed it out myself.

If your memory is so poor there's no point in carrying on this conversation.

I would like to point out one thing, though:

> >No, just difficult. Like many things in small operating systems running
> >on hardware with no MMU, you have to work harder to accomplish the same
> >thing.

> We have been talking about UNIX. I don't want to continue the meaningless
> discussion by enlarging domain.

UNIX runs, and has run, on hardware with no MMU. Small PDP-11s, 68000s...
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

peter@ficc.ferranti.com (Peter da Silva) (08/07/90)

In article <b7llec8d@myrias.com> dab@myrias.com (Danny Boulet) writes:
> with the signal set to SIG_DFL.  For example, if the parent wants to run with
> ^C always disabled but wants to start a child with ^C enabled, the scheme
> you propose creates a window for the ^C to sneak through

Not if you use reliable signals (for example, System V sigset()).
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>