[comp.unix.questions] Fork and Join, Pipe in C

guy@gorodish.UUCP (06/08/87)

>   I am currently working on my research using C concurrent programming
> technique of fork & join and pipe.

This isn't a C technique, it's a UNIX technique.  I'm redirecting
further discussion to comp.unix.questions/INFO-UNIX.

>    Are there any other ways of creating more than one child at a time.
>    The method I am using is read in the number of processes and use
>    this variable to determine the number of children to fork using
>    a simple FOR loop in C.

No, there is no way in UNIX to create processes other than "fork",
and that only creates one at a time.

> Are there any books on these topics.

There are lots of books on programming under UNIX, some of which will
discuss this.  There's a book by Brian Kernighan and Rob Pike, titled
"The UNIX Programming Environment", which has been highly recommended
by many people.  (I don't know if it discusses this or not.)  There
is also a document called "UNIX Programming", by Kernighan and
Ritchie, that comes with various versions of UNIX.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

mikep@ism780c.UUCP (06/10/87)

In article <20616@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>
>No, there is no way in UNIX to create processes other than "fork",
>and that only creates one at a time.
>
>> Are there any books on these topics.
>
>There are lots of books on programming under UNIX, some of which will
>discuss this.  There's a book by Brian Kernighan and Rob Pike, titled
>"The UNIX Programming Environment", which has been highly recommended
>by many people.  (I don't know if it discusses this or not.)  There
>is also a document called "UNIX Programming", by Kernighan and
>Ritchie, that comes with various versions of UNIX.

There is another book that is much better than "The UNIX Programming
Environment" for this and it is called, "Advanced UNIX Programming" by Marc
J. Rochkind.  This book is also put out by Prentice Hall, and describes
the UNIX System call level more thoroughly than any other book I've
seen.  It's also very interesting bathroom reading...


-------------------------------------------------------------------------------
The company and all my associates and friends and ESPECIALLY the 
government put me up to say all this useless trash.
|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|
MikeP     sdcrdcf!\                     "Some of my best friends are Bigots..."
                   >-- ism780c!mikep    
           seismo!/                     
                                       

mj@elmgate.UUCP (06/15/87)

> Are there any books on these topics.

	Yet another good book on UNIX (although probably too advanced for the
	fork/join/pipe questions) is THE DESIGN OF THE UNIX OPERATING SYSTEM
	by Maurice Bach, c. 1986, Bell Telephone Laboratories (Prentice-Hall
	software series).  In this book, Bach describes the internal data
	structures and algorithms of the kernel, and details how
	these support the user interface.  As a Unix programmer who
	understands most of the system calls fairly well and would like
	to begin digging at the kernel,  I have found this books to be
	complete and informative.  The Advanced UNIX Programming book
	mentioned earlier is also very good.

-------------------------------------------------------------------------------
Mark A Johnson - Eastman Kodak Co. - Dept 646 - KEEPS - Rochester, NY 14650
The opinions expressed above are not necessarily those of Eastman Kodak Company
and are entirely my responsibility.

guy%gorodish@Sun.COM (Guy Harris) (06/22/87)

(Again, we redirect this to comp.unix.questions/INFO-UNIX.)

> If vfork is much faster (as opposed to slightly faster) than fork, it is
> time to complain to the supplier of your Unix, asking why he hasn't
> implemented fork efficiently.  Even Berkeley *intended* to fix this, as
> witness the comments on the vfork manual page.  Sensible vendors have
> long since implemented copy-on-write fork, which eliminates most of the
> copying involved in fork, thus eliminating most of the reason to use the
> ugly and brain-damaged vfork.

Or, at least, sensible vendors that are implementing on hardware that
provides the ability to specify, with a relatively small granularity,
regions of a process' address space such that attempts to modify them
will cause traps.  If, for example, you are stuck with
write-protecting the entire data or stack segment, copy-on-write may
not buy you much.  Fortunately, most machines don't impose obnoxious
restrictions of that flavor.

The only remaining reason to use vfork is that one has written ugly
and brain-damaged code that depends on the semantics of "vfork".
Such code does, unfortunately, exist; one of the pre-releases of
4.3BSD used this crock in "find", but it was fixed before 4.3BSD went
out the door in its final form.  If anybody has written code of this
sort, they should hang their head in shame and then go out and fix it
NOW.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

lm@cottage.WISC.EDU (Larry McVoy) (06/22/87)

In article <21685@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
$ The only remaining reason to use vfork is that one has written ugly
$ and brain-damaged code that depends on the semantics of "vfork".

Well, now, I'm not quite sure I agree with this.  I'll admit that taking
advantage of the semantics of a doomed system call is ugly.  But suppose
I were to phrase it like this:  I wasn't taking advantage of vfork, I 
just had a need for shared memory.  Then it's probably ok, right? 
Everyone thinks shm is great, n'est pas?  (So when are we going to see
shm in 4.x?  Hmm?)

Don't misunderstand me - I'm not telling you to use vfork - I'm just
pointing out that code that uses the semantics of vfork is not
necessarily "ugly and brain-damaged."


Larry McVoy 	        lm@cottage.wisc.edu  or  uwvax!mcvoy

guy%gorodish@Sun.COM (Guy Harris) (06/22/87)

> Well, now, I'm not quite sure I agree with this.  I'll admit that taking
> advantage of the semantics of a doomed system call is ugly.  But suppose
> I were to phrase it like this:  I wasn't taking advantage of vfork, I 
> just had a need for shared memory.  Then it's probably ok, right? 

No!  For one thing, the system call *is* doomed, and future implementations
of "vfork" may not *give* you shared memory; in that case, your
program will silently stop working.  For another, you don't
necessarily get *useful* shared memory - after a "vfork", the parent
is blocked until the child either exits or does an "exec", releasing
the shared memory.

> Everyone thinks shm is great, n'est pas?

Yes, shared memory is nice, but "vfork" *isn't* a mechanism for
getting shared memory.

> (So when are we going to see shm in 4.x?  Hmm?)

Don't ask me, I'm not responsible for 4.x.

> Don't misunderstand me - I'm not telling you to use vfork - I'm just
> pointing out that code that uses the semantics of vfork is not
> necessarily "ugly and brain-damaged."

Yes, it is.  There is very little you can do with the (temporarily) shared
memory you get from "vfork", and in most, if not all, cases, you can
do the same thing just as well without it.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

schoch@ames.arpa (Steve Schoch) (06/24/87)

In article <21731@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>  There is very little you can do with the (temporarily) shared
>memory you get from "vfork", and in most, if not all, cases, you can
>do the same thing just as well without it.

Try the built-in command "hashstat" in csh.  It's to be used mostly for
debugging, I assume, as it tells you how well the exec hash table is working.
The way it counts a "miss" is by incrementing a variable everytime a exec
fails.  It has to do this in the child, and thus uses the vfork "shared
memory".

	Steve

guy%gorodish@Sun.COM (Guy Harris) (06/24/87)

> Try the built-in command "hashstat" in csh.  It's to be used mostly for
> debugging, I assume, as it tells you how well the exec hash table is working.
> The way it counts a "miss" is by incrementing a variable everytime a exec
> fails.  It has to do this in the child, and thus uses the vfork "shared
> memory".

It could also do this with a shared file; abusing "vfork"s shared memory
may have been convenient, but it wasn't necessary.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

tytso@athena.mit.edu (Theodore Y. Ts'o) (06/25/87)

In article <21928@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>> Try the built-in command "hashstat" in csh.  It's to be used mostly for
>> debugging, I assume, as it tells you how well the exec hash table is working.
>> The way it counts a "miss" is by incrementing a variable everytime a exec
>> fails.  It has to do this in the child, and thus uses the vfork "shared
>> memory".
>
>It could also do this with a shared file; abusing "vfork"s shared memory
>may have been convenient, but it wasn't necessary.

What about the overhead to update said shared file every time you
execute a command?  I think I prefer the "abuse" of the shared memory.
The main purpose of vfork was to enhance csh's effiency anyway.


=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
Theodore Ts'o                           |
mit-eddie!mit-athena!tytso              |     M.I.T.,
tytso@athena.mit.edu                    |        P.h.D.,
3 Ames St., Cambridge, MA 02139         |            M.O.N.E.Y.!
                                        |
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

guy%gorodish@Sun.COM (Guy Harris) (06/25/87)

> What about the overhead to update said shared file every time you
> execute a command?

Try it first, see how much the overhead really is, then complain.
Don't assume it'll have to be so large as to render abusing "vfork"
acceptable; it may very well not be noticeable.

> I think I prefer the "abuse" of the shared memory.

I hope you also prefer explaining to somebody why the function that
abuses "vfork" mysteriously fails under 4.nBSD, for some n > 3, or on
some box with a VM system that uses copy-on-write and thus implements
"vfork" as an alias for "fork" - and do so with NO complaints about
such implementations, as those complaints are completely unjustified.
I quote from the 4.3BSD manual page for "vfork":

	This system call will be eliminated when proper system sharing
	mechanisms are implemented.  Users should not depend on the memory
	sharing semantics of "vfork" as it will, in that case, be made
	synonymous to "fork".

Note especially the absence of the word "may" here - the word "will"
appears twice, so one presumes they wanted people to take this
warning seriously.  However, somebody decided this didn't apply to
them and went ahead and depended on those semantics anyway.

> The main purpose of vfork was to enhance csh's effiency anyway.

Yes, but the efficiency improvement due to eliminating a copy of the
entire data and stack segment was large; I've seen no evidence that
there would be any major efficiency improvement due to abusing
"vfork".  We're talking about a very small amount of data here (it
should fit into one frag), and that data is modified only if an
"exec" fails.  "exec"s shouldn't fail, in general, especially given
the C shell's path hashing.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

tytso@athena.mit.edu (Theodore Y. Ts'o) (06/26/87)

In article <22057@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>> I think I prefer the "abuse" of the shared memory.
>
>I hope you also prefer explaining to somebody why the function that
>abuses "vfork" mysteriously fails under 4.nBSD, for some n > 3, or on
>some box with a VM system that uses copy-on-write and thus implements
>"vfork" as an alias for "fork" - and do so with NO complaints about
>such implementations, as those complaints are completely unjustified.

For some n>3, /bin/csh will presumably be updated when vfork changes.
If some VM system implements a copy-on-write fork and changes vfork on
NOW, they will break csh.

>I quote from the 4.3BSD manual page for "vfork":
>
>	This system call will be eliminated when proper system sharing
>	mechanisms are implemented.  Users should not depend on the memory
				     ^^^^^
>	sharing semantics of "vfork" as it will, in that case, be made
>	synonymous to "fork".
>

/bin/csh is a system program.  USERS can write such programs at their
own risk.

>> The main purpose of vfork was to enhance csh's effiency anyway.
>
>Yes, but the efficiency improvement due to eliminating a copy of the
>entire data and stack segment was large; I've seen no evidence that
>there would be any major efficiency improvement due to abusing
>"vfork".  We're talking about a very small amount of data here (it
>should fit into one frag), and that data is modified only if an
>"exec" fails.  "exec"s shouldn't fail, in general, especially given
>the C shell's path hashing.

A hashstat on my workstaion shows 26%.  Other hosts that I'm logged
into show hit ratios of about 40%.  Our environment requires
relatively long search paths.  


=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
Theodore Ts'o                           |
mit-eddie!mit-athena!tytso              |     M.I.T.,
tytso@athena.mit.edu                    |        P.h.D.,
3 Ames St., Cambridge, MA 02139         |            M.O.N.E.Y.!
                                        |
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

guy%gorodish@Sun.COM (Guy Harris) (06/26/87)

> For some n>3, /bin/csh will presumably be updated when vfork changes.
> If some VM system implements a copy-on-write fork and changes vfork on
> NOW, they will break csh.

No, they will NOT!  They will merely reveal that "csh" is ALREADY broken
by virtue of relying on something that was *explicitly documented* as
a quirk of the implementation that was not to be relied on.  It is
perfectly legitimate to provide a system with vfork == fork, and any
complaints from programmers whose improperly-written programs cease
to work should be redirected to /dev/null.

> /bin/csh is a system program.  USERS can write such programs at their
> own risk.

The trouble is that many users would squeal anyway, despite the fact
that they were explicitly told not to write this kind of program and
that they do so at their own risk.  (Consider the possibly-apocryphal
story of the person who bought and wrecked a Ferrari, and then sued
because (s)he wasn't told that it was a "high-performance car".)  It
appears that points such as this need to be reiterated over and over
again to ensure that people are aware of them.

Furthermore, the fact that "/bin/csh" is a system program doesn't
change the fact that there is no indication that, if you change the
semantics of "vfork", it breaks - if somebody ports 4BSD and
implements a better VM system, and makes vfork == fork (which the
manual at least implies should be possible with such a VM system),
without changing "csh", "csh" won't work.

> A hashstat on my workstaion shows 26%.  Other hosts that I'm logged
> into show hit ratios of about 40%.  Our environment requires
> relatively long search paths.  

OK, but you still haven't provided any evidence that there would be a
major performance hit from using the file rather than abusing
"vfork".  Go implement it, test it, and *then* argue one way or the
other about whether it's a good thing to ignore what the manual says
about "vfork" or not.  (The burden of proof here is on the person who
argues that the manual's warning should be ignored.)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

lm@cottage.WISC.EDU (Larry McVoy) (06/27/87)

In article <22181@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
$ > For some n>3, /bin/csh will presumably be updated when vfork changes.
$ > If some VM system implements a copy-on-write fork and changes vfork on
$ > NOW, they will break csh.
$ 
$ No, they will NOT!  They will merely reveal that "csh" is ALREADY broken
$ by virtue of relying on something that was *explicitly documented* as
$ a quirk of the implementation that was not to be relied on.  

Lighten up, Guy, you sound hysterical.  Csh is not "broken", at least not 
by any reasonable definition - it runs, does it not?  Lots  of people use 
it every day.  

Furthermore, do you realize how ridiculous it is to say that csh is broken
due to its use of vfork()?  Correct me if I am wrong (I'm sure you will)
but I believe vfork() was implemented *specifically* for csh.  Irregardless
of what the man page says (you listen to man pages?  Use the force, read the
source) the definitive use of vfork() is how it is used in csh.


Larry McVoy 	        lm@cottage.wisc.edu  or  uwvax!mcvoy

schoch@ames.arpa (Steve Schoch) (06/27/87)

In article <22181@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
> ...if you change the
>semantics of "vfork", it breaks - if somebody ports 4BSD and
>implements a better VM system, and makes vfork == fork (which the
>manual at least implies should be possible with such a VM system),
>without changing "csh", "csh" won't work.

Well, actually, it won't "break" csh, the "hashstat" built-in will just
not print anything.  It will still give (status == 0) and everything else
will work as before.  We found this out when we had a system where vfork
didn't work yet, so it just called fork() in the kernel.

The idea is that csh will use the "shared memory" feature of vfork while
it's there, but won't complain if it's not.  Of course, if some user gets
used to typing "hashstat" and expects it to print something, he will complain.
I don't know who uses that function anyway.

	Steve

guy%gorodish@Sun.COM (Guy Harris) (06/27/87)

> but I believe vfork() was implemented *specifically* for csh.

"vfork" was implemented for the benefit of various programs, "csh"
among them.  However, the fact that the current implementations of
"vfork" give you a limited form of shared memory was purely a
consequence of the implementation; it was not a "feature" stuck in
for the benefit of any program, and if it disappears *nobody* has the
right to complain *at all*.

Unfortunately, some person who decides that warnings in the manual
page don't apply to them will use this feature anyway and complain
bitterly that somebody "broke" vfork if it is reimplemented so as not
to provide that sort of shared memory.  The warnings about "vfork"
have to be repeated simply in the hopes that some form of conditioned
reflex will be established amongst most programmers so that they
don't force implementors to provide this explicitly deprecated
side-effect of "vfork".

> Irregardless of what the man page says (you listen to man pages?  Use
> the force, read the source) the definitive use of vfork() is how it is
> used in csh.

Bullshit.  First of all, the line "Use the force, read the source" is
descriptive of a deficiency in UNIX, not of an advantage of UNIX.
One is forced to read the source in some cases because the UNIX
documentation is either 1) incorrect, 2) unclear, or 3) incomplete.
The UNIX documentation *should* be correct, clear, and complete; the
fact that it isn't merely means more work should be done on it.

Second of all, in this particular case the UNIX documentation *is*
correct, clear, and complete.  It tells you that these semantics of
"vfork" are a side-effect of the current implementation, not a
deliberate feature of the interface.  The fact that the source of a
*particular* UNIX implementation indicates that those semantics are
provided does not mean that those semantics are a characteristic of
the interface, and the fact that some piece of code knows that the
implementation works in this fashion does not mean that "vfork" is
intended to work in this fashion.  (The fact that some 4.1BSD code
used NULL as the name of a null character string most definitely does
not mean that NULL *is* the name of a null character string!  That is
an unfortunate characteristic of the VAX UNIX implementation; had it
not been, a lot of people at a number of computer companies might
have spent less time fixing other people's bugs.)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

throopw@xyzzy.UUCP (Wayne A. Throop) (06/27/87)

> guy%gorodish@Sun.COM (Guy Harris)
> The only remaining reason to use vfork is that one has written ugly
> and brain-damaged code that depends on the semantics of "vfork".

But fork() can *never* be as efficent as vfork(), and sometimes this
efficency is crucial.  Even if you can create copy-on-demand during
fork(), the database needed to keep track of these pages consumes kernel
(possibly virtual) memory space, and the creation and upkeep of this
data consumes kernel CPU time.  The vfork() is hinting to the kernel
that an exec() is about to occur, and therefore the kernel is
well-advised not to invest much in the correct copy of the address
space.

That said, I agree that vfork is a horrible kludge.  What *should* have
been coined is the ability to create a process running a new executable
image in a single system call.  This is the only way the kernel can be
*assured* (rather than simply having it hinted at) that this process
creation will not involve the copying of any memory from the parent
process.  The fork() operation is still interesting and necessary, and
the exec() operation is still interesting and necessary, but so is the
create_process() operation.  If you think the operation is not
interesting and common, note how many zillions of library routines use
fork() or vfork() immediately followed by exec(), and provoke the kernel
into doing all sorts of unnecessary work, even if that kernel implements
copy-on-demand.

The counterargument is that each system call should do only one thing,
and they should be combined to make more complicated operations.  In
this sense, I agree that only fork() and exec() are needed.  But
engineers don't build out of nand-gates only, though that is all that is
logically necessary.  They use gates that more clearly convey intent,
and thus can gain significant efficency.  Similarly, create_process()
guarantees the kernel important information about the programmer's
intent that combinations of fork() and exec() do not, and in this case I
think the practical benefits of create_process() outweigh the
theoretical benefits of a "pure" "simple" set of system calls.

To finish off, let's look at the capabilities of fork() and exec() layed
out in a table:

                                load image      create process
        --------------------+---------------------------------
        do nothing          |   no              no
        fork()              |   no              yes
        exec()              |   yes             no
        create_process()    |   yes             yes

I think it is clear that there "ought" to be a create_process(), despite
the fact that it can be created out of fork() followed by exec(),
because despite all tricks, fork() needs to get a process memory image
from somewhere, and this will always come at some cost.

(Although, strangely enough, I will not argue that there ought to be a
 do_nothing() system call...)

--
An operating system is a set of manual and automatic procesures that
enable a group of people to share a computer installation efficently.
                                --- Per Brinch Hansen
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

throopw@xyzzy.UUCP (Wayne A. Throop) (06/27/87)

> throopw@xyzzy.UUCP (Wayne A. Throop)
> [...] vfork is a horrible kludge.  What *should* have
> been coined is the ability to create a process running a new executable
> image in a single system call.  This is the only way the kernel can be
> *assured* (rather than simply having it hinted at) that this process
> creation will not involve the copying of any memory from the parent
> process.  

Another way to reinforce this point just occured to me, and that is to
point out a case where (I think) Berkeley got it right (though perhaps
for other reasons).

There is a close analogy to fork(), exec(), and create_process() in
link(), unlink(), and rename().  Obviously, link() and unlink() in
combination suffice to rename files.  But some extra efficency (though,
granted, I think efficency was not the major consideration) can be added
by hinting to the kernel that an unlink() will follow the link()
(avoiding the necessity to change the link count and so on) by
introducing the system call vlink().  This would create a link() but not
increment the link count, allowing the new link to "share" one of the
existing ones, because one of them is about to go away.

Happily, the Berkeley implementors didn't do that.  They implemented
rename() instead.  And similarly, they should have implemented
create_process() instead of vfork().

(Or did rename() come from NFS?  Hmmmm.  Now I'm confused.  But the
 point remains valid in either event.)

--
Adam and Eve had many advantages, but the principal one
was, that they escaped teething.
                --- Pudd'nhead Wilson's Calendar (Mark Twain)
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

tytso@athena.mit.edu (Theodore Y. Ts'o) (06/28/87)

In article <22241@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>> but I believe vfork() was implemented *specifically* for csh.
>
>"vfork" was implemented for the benefit of various programs, "csh"
>among them.  However, the fact that the current implementations of
>"vfork" give you a limited form of shared memory was purely a
>consequence of the implementation; it was not a "feature" stuck in
>for the benefit of any program, and if it disappears *nobody* has the
>right to complain *at all*.
>
>Unfortunately, some person who decides that warnings in the manual
>page.....

*WHAT* warnings in the man pages?  The only thing coming close to what
you're saying is the BUGS entry where it says that it "will be
eliminated when proper system sharing mechanisms are implemented."
This implies that future *VERSIONS* of BSD have the right to change
the meaning of vfork, NOT future *IMPLEMENTATIONS*.  Since /bin/csh is
maintained by Berkeley, when they change vfork, I expect they will
update /bin/csh as well.

>Bullshit.  First of all, the line "Use the force, read the source" is
>descriptive of a deficiency in UNIX, not of an advantage of UNIX.
>One is forced to read the source in some cases because the UNIX
>documentation is either 1) incorrect, 2) unclear, or 3) incomplete.
>The UNIX documentation *should* be correct, clear, and complete; the
>fact that it isn't merely means more work should be done on it.

It's been said that UNIX is a OS writen by, and for, systems
programers.  Systems programmers writing documentation? :-)
Seriously, I know they should, but you may be expecting a little bit
too much of human nature.....


>Second of all, in this particular case the UNIX documentation *is*
>correct, clear, and complete.  It tells you that these semantics of
>"vfork" are a side-effect of the current implementation, not a

Where?  See above.  I think that you differ with everybody else on the
interpretation of the man pages.  But at least mine (BSD 4.3) says
absolutely nothing about vfork being implementation dependant.  You
may be reading a little bit too much into the man page here.

> [flames about how programs that know too much about the
> implementation of UNIX and rely upon them are broken]

Fine, but how do you know what is a "implementation detail" and what
is a part of the system call standard interface.  By placing a
description of how vfork works in the man pages, that becomes part of
the interface.  If I write a program that uses vfork in a clever way,
but one that is COMPLETELY DOCUMENTED IN THE MAN PAGES, I expect that it
should work in any implementation of UNIX that claims to be BSD 4.3.
If it doesn't work, it isn't 4.3.  Sure it should have been made
more portable.  But when you have a program like /bin/csh, which is
ditributed under the assumption that it will run only under 4.3, 
(since it's distributed with it :-8) it's perfectly justified, don't
you think? 

>	Guy Harris
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
Theodore Ts'o                           |
mit-eddie!mit-athena!tytso              |     M.I.T.,
tytso@athena.mit.edu                    |        P.h.D.,
3 Ames St., Cambridge, MA 02139         |            M.O.N.E.Y.!
                                        |
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

lm@cottage.WISC.EDU (Larry McVoy) (06/28/87)

In article <22241@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
$ > but I believe vfork() was implemented *specifically* for csh.
$ 
$ "vfork" was implemented for the benefit of various programs, "csh"
$ among them.  

Sorry, Guy, but you are wrong.  I suggest you do a little more background
reading.  I did some digging and came up with the paper which says that
vfork() was for csh.  The paper is "Converting a Swap based System to do
Paging in an Architecture Lacking Page-Reference Bits" by Babaoglu & Joy,
1981 ACM.  They specifically state that "We found the vast majority (over
80%) of all forks executed in the system were due to the command interpreter
[ie, csh]."  They go on to point out that they implemeted vfork() to get
around this problem.  It's all there on page 81, check it and see.

To be sure that they were indeed talking about csh all one has to do is

    % cd /usr/src/bin/sh
    % fgrep vfork *.[ch]

Which I did.  No vfork().  The bottom line is:  vfork was put in for csh.
Specifically for csh.  Not in part, not as a general tool, specifically for
csh.  

$ > Irregardless of what the man page says (you listen to man pages?  Use
$ > the force, read the source) the definitive use of vfork() is how it is
$ > used in csh.
$ 
$ Bullshit.  

No Guy, not bullshit, true shit.  Vfork() was put in specifically for
csh.  Any way that it is used in that program should be looked upon as
a legitimate use of the system call.  Saying otherwise is ridiculous.

$ First of all, the line "Use the force, read the source" is
$ descriptive of a deficiency in UNIX, not of an advantage of UNIX.
$ One is forced to read the source in some cases because the UNIX
$ documentation is either 1) incorrect, 2) unclear, or 3) incomplete.
$ The UNIX documentation *should* be correct, clear, and complete; the
$ fact that it isn't merely means more work should be done on it.

Yeah - and just when is that work scheduled for completion?  Real soon
now, eh?  This business about Unix documentation is a joke.  Only trivial
things are documented well.  Anything complicated is, as has been pointed
out before, addendumed by a lengthy bugs section or is just quiet.  

Case in point-  I couldn't get to source for a weekend and my work came
to screeching halt.  I really hadn't realized how much I leaned on it
but I'd say I pop over and look a couple of times a day.  And I'm writing
user level code.  There's no excuse for that crap.

Larry McVoy 	        lm@cottage.wisc.edu  or  uwvax!mcvoy

guy%gorodish@Sun.COM (Guy Harris) (06/28/87)

> *WHAT* warnings in the man pages?  The only thing coming close to what
> you're saying is the BUGS entry where it says that it "will be
> eliminated when proper system sharing mechanisms are implemented."

I quote from the manual, which you appear not to have read carefully:

	This system call will be eliminated when proper system sharing
	mechanisms are implemented.  *Users should not depend on the
	memory sharing semantics of "vfork" as it will, in that case,
	be made synonymous to "fork".*  ("italics" mine)

Now, to me that says you shouldn't write code like the code in question.  The
fact that it may happen to work *now* does not mean that it is
specifically *intended* to work that way.  It didn't say "be prepared
to change your code when 'vfork' changes", it said "don't do this".
It says so quite clearly, and gives no exceptions.

> It's been said that UNIX is a OS writen by, and for, systems
> programers.  Systems programmers writing documentation? :-)

If UNIX is an OS written by and for systems programmers, it should
have remained a laboratory curiosity.  Very few programmers are
systems programmers, and at this point very few computer users are
programmers.  UNIX is, however, no longer a laboratory curiosity.
There is *no* excuse for shabby documentation any more.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

guy%gorodish@Sun.COM (Guy Harris) (06/28/87)

> Sorry, Guy, but you are wrong.  I suggest you do a little more background
> reading.

Sorry, Larry, but you are, as usual, wrong.  I suggest you look in
the source directory for "make" and note that it also uses "vfork",
then check out "find", which also uses it (and, in the alpha version,
ABused it - that was fixed for the final version) and then look at
the source to the "popen" routine - it also uses "vfork".  It may
have been put in to speed up "csh", but concluding from this that it
was *not* indended to be used by anybody else is absurd.

> No Guy, not bullshit, true shit.  Vfork() was put in specifically for
> csh.  Any way that it is used in that program should be looked upon as
> a legitimate use of the system call.  Saying otherwise is ridiculous.

No, saying what you just said is ridiculous, considering that the use
of "vfork" in question is specifically recommended *against* by the
manual!  If they had intended that it be used in that fashion, they
wouldn't have told you not to use it in that fashion.

> Yeah - and just when is that work scheduled for completion?  Real soon
> now, eh?  This business about Unix documentation is a joke.  Only trivial
> things are documented well.  Anything complicated is, as has been pointed
> out before, addendumed by a lengthy bugs section or is just quiet.

This is true, but accepting it as "the way of the world" and doing
nothing to fix it is asinine.  Various vendors have done some good
work on fixing the UNIX documentation.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.ltin

guy%gorodish@Sun.COM (Guy Harris) (06/28/87)

> But fork() can *never* be as efficent as vfork(), and sometimes this
> efficency is crucial.

Yes, there is a savings if you can avoid copying the VM data
structures, but this savings will be less than the savings from not
copying the pages themselves.  I'm not convinced that this savings
will necessarily be enough to justify "vfork".  (TOPS-20, and I
presume TENEX, had the equivalent of "fork" and "exec", and used
copy-on-write, but didn't provide the equivalent of "vfork".  I don't
know if they just didn't bother or if they determined that it
wouldn't be worth it.  It may be that on systems other than 10s and
20s, or OSes other than TOPS-20/TENEX, the overhead of copying the VM
data structures would be greater, due to larger address spaces,
smaller page sizes, more complicated data structures, etc..)

> If you think the operation is not interesting and common, note how many
> zillions of library routines use fork() or vfork() immediately followed
> by exec(), and provoke the kernel into doing all sorts of unnecessary
> work, even if that kernel implements copy-on-demand.

Sometimes "fork" or "vfork" is *not* immediately followed by "exec".
If the program to be run in the new process is not to inherit its set
of open files from its parent, the child process has to rearrange the
file descriptors before doing an "exec".

The "create_process" call would have to include options for closing
descriptors, opening files, and moving descriptors around.  (This is
the approach taken in VMS; the SYS$CREPRC call includes options for
redirecting various I/O channels.)  It might also have to include
options for manipulating signals.

A lot of systems don't provide separate "fork" and "exec" calls, but
do provide a call like "create_process".

(BTW, "rename" had nothing to do with NFS; it appeared in 4.2BSD.)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

tytso@athena.mit.edu (Theodore Y. Ts'o) (06/29/87)

In article <22253@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>I quote from the manual, which you appear not to have read carefully:
>
>	This system call will be eliminated when proper system sharing
>	mechanisms are implemented.  *Users should not depend on the
				     ^^^^^^
>	memory sharing semantics of "vfork" as it will, in that case,
>	be made synonymous to "fork".*  ("italics" mine)

You appear not to have read my *POSTING* carefully.  To summarize yet
again: 

1)  /bin/csh is a system program, not a user program.  It never says
that system programs distributed by BSD may not use this call, and the
BUGS entry of programs that use this call do not consider the fact that
they use vfork a bug.  

2)  The man page implies that future versions of *BSD* may change vfork.
Nowhere in the man page does it say that it is IMPLEMENTATION
dependant.

3)  Since the man page specifcally goes into painful detail how vfork
works, the schemamtics of vfork have become part of the BSD 4.3 system
interface.  Any implementation that changes the meaning of vfork is not
"FULL" BSD 4.3. 

-------------------------

All of the sources that I (and other people) have consulted say that
vfork was implemented specifically for /bin/csh.  Your arguments simply
point to the source code of various programs/routines, like make and 
popen.  Which came first, the chicken or the egg?  I (and several other
people) have documentation that vfork was implemented specifically and
originally for /bin/csh.  Do us the favor of finding some documented
evidence to the contrary if you believe otherwise.

----------------------------

This is beginning to turn into a religious war.  When ad hominum attacks: 
> Sorry, xxxxx, but you are, as usual, wrong. 
			     ^^ ^^^^^
start creeping into the discussion, perhaps we should find something
else to discuss, hmm?  Unless one of us plans to write BSD 4.4, most of
this becomes mostly pointless and moot anyway.
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
Theodore Ts'o                           |
mit-eddie!mit-athena!tytso              |     M.I.T.,
tytso@athena.mit.edu                    |        P.h.D.,
3 Ames St., Cambridge, MA 02139         |            M.O.N.E.Y.!
                                        |
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

jpn@teddy.UUCP (John P. Nelson) (06/29/87)

>There is a close analogy to fork(), exec(), and create_process() in
>link(), unlink(), and rename(). ... some extra efficency can be added
>by hinting to the kernel that an unlink() will follow the link()
>(avoiding the necessity to change the link count and so on) by
>introducing the system call vlink().

The situations are NOT analogous.  One of the most common operations
done between an fork and an exec is the modifications of the file
descriptors.  Tell me, with create_process, just how would you create
an inter-process pipe?  The standard code is:

    pipe(fds)
    if (fork() == 0)
	{
	dup2(fds[1], 1);
	close(fds[0]);
	close(fds[1]);
	exec(...);
	}
    close(fds[0]);

Unless create_process allows for modification of the file descriptors, it will
be of limited utility.

ron@topaz.rutgers.edu (Ron Natalie) (06/29/87)

> But fork() can *never* be as efficent as vfork(), and sometimes this
> efficency is crucial.  Even if you can create copy-on-demand during
> fork(), the database needed to keep track of these pages consumes kernel
> (possibly virtual) memory space, and the creation and upkeep of this
> data consumes kernel CPU time.

Crap.  No extra space is involved as there are already unused bits in
the page tables in most implementations.  The few systems that already
do copy-on-write forking don't end up using any additional CPU time.
The MMU is what keeps track of write references (it is already doing
this for "references" without differentiating writes and reads).
What extra CPU overhead is it for machines that have decent virtual
memory.  VFORK exists only for people who don't share memory well in
hardware.

Note that FORK-AND-EXEC won't solve any but the most simple cases.
The csh needs to twiddle process groups and file descriptors after
the fork as do popen and other library calls.

-Ron

lm@cottage.WISC.EDU (Larry McVoy) (06/29/87)

Guy sez:
	vfork() was invented for all sorts of programs.

I sez:
	Guy is wrong, since vfork() was invented for csh.  On my side of the 
	ring we have the words of Bill Joy and others in published docs.
	(Note-  I never said that vfork() is only for csh, only that it was
	invented for csh.)

Guy sez:
	Larry is wrong, 'cause make & popen use vfork().

And now I sez:
	[Are we having fun yet????]

	Guy, don't be an ass.  We were talking about the *creation* of the
	system call.  

	You know, the funny thing is that I agree in principle with what Guy
	said in the first place - vfork() users probably ought not to pook
	about in their parent's address space.  What I didn't agree with,
	and what probably bothered other people, is Guy's statement that 
	"All programs that use vfork in this manner are brain damaged".
	That's an awfully strong statement and is just about impossible
	to back up.  All one has to do to disprove it is show one program
	for which that statement is false.  And the funny thing is that 
	the very first program to use vfork (csh) needed to be able to
	pook about in the parent's address space.  

	So what's the big deal, Guy?  Obviously, csh will have to be fixed
	when they throw out vfork().  But it won't be hard - they'll probably
	have shared memory by then and people can do it that way.  Whatever
	fix is used for csh can also be applied to similar programs.  So,
	I say - use vfork() anyway you like, just be prepared to support
	new VM models.  I don't see a big problem.  I mean, is all of
	Berkeley running around chewing their nails over this?  Then
	why are we?

	'Nuff said.  I hope.

Larry McVoy 	        lm@cottage.wisc.edu  or  uwvax!mcvoy

guy@gorodish.UUCP (06/29/87)

> 1)  /bin/csh is a system program, not a user program.  It never says
> that system programs distributed by BSD may not use this call, and the
> BUGS entry of programs that use this call do not consider the fact that
> they use vfork a bug.  

Dammit, nobody was saying that the fact that they use "vfork" *was* a
bug!  The fact that they abuse a side-effect of the implementation of
"vfork", in a fashion that the manual page *explicitly says not to*,
is the problem.

> 2)  The man page implies that future versions of *BSD* may change vfork.
> Nowhere in the man page does it say that it is IMPLEMENTATION
> dependant.

It should be fairly clear from the manual page that the *intent* of
"vfork" was NOT to permit sharing of address space between parent and
child, but to reduce the ovehead of creating a child.

> 3)  Since the man page specifcally goes into painful detail how vfork
> works, the schemamtics of vfork have become part of the BSD 4.3 system
> interface.  Any implementation that changes the meaning of vfork is not
> "FULL" BSD 4.3.

The manual page also specifically goes into detail about how you are
NOT supposed to depend on those semantics; this would appear to
indicate that the fact that the current 4BSD implementation of
"vfork" causes the parent and child to temporarily share memory was
most definitely NOT intended to be a feature of "vfork".  Manual
pages will sometimes describe implementation details without making
them part of the specification.

> All of the sources that I (and other people) have consulted say that
> vfork was implemented specifically for /bin/csh.  Your arguments simply
> point to the source code of various programs/routines, like make and 
> popen.  Which came first, the chicken or the egg?  I (and several other
> people) have documentation that vfork was implemented specifically and
> originally for /bin/csh.  Do us the favor of finding some documented
> evidence to the contrary if you believe otherwise.

What does "implemented specifically for '/bin/csh'" mean?  Does it
mean that it was not intended to be used by anybody else?  Obviously
not, since they documented it in enough detail for others to use
(AND, I repeat, in enough detail to strongy discourage people from
abusing the fact that the implementation caused the parent and the
child to share portions of their data space!), and since it was used
elsewhere.

The only way in which it was "implemented specifically for
'/bin/csh'" was that the program that caused them to *notice* that
providing "vfork" would increase performance was "/bin/csh".

Sigh.  If anybody STILL thinks that it's OK to rely on the shared
memory that the current "vfork" implementation provides, and that
this shared memory is a feature of the specification, not a
characteristic of the implementation, would they please explain why
the manual page specifically tells you NOT to rely on this?  All the
people who seem eager to consider the implementation to be the
specification have failed to address this point.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

guy%gorodish@Sun.COM (Guy Harris) (06/30/87)

> 	We were talking about the *creation* of the system call.  

Which is totally irrelevant.  I see no evidence that they did not intend other
code to use "vfork"; "csh" just happened to contain the code that
suggested its creation.

> 	And the funny thing is that the very first program to use vfork
>	(csh) needed to be able to pook about in the parent's address space.

Some people have a very funny notion of the meaning of the word
"need".  I have seen no evidence that "hashstat" *required* that
"vfork" be abused, merely that it happened to be convenient to do so.
A heck of a lot of crocks are created in the name of convenience.

There are entirely too many programmers out there who are quick to
take advantage of characteristics of the way some function is
implemented without considering whether this is really a good idea.
It should be made clear that this is a Bad Idea, and justifiable ONLY
if it is the lesser of two or more evils.

Unfortunately, there seems to be a large segment of the UNIX
community that sees little or nothing wrong with this.  This causes
enough problems with non-portable OSes (I'm sure there are stories
about programs "broken" by changes to VMS, where the fault lies
*entirely* with the authors of those programs, not with DEC, as the
authors in question were relying on the system continuing to work the
way they "knew" it worked), but can cause even more problems with
UNIX, as there will be several different implementations of the
*same* interface.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

jerry@oliveb.UUCP (Jerry F Aguirre) (06/30/87)

In article <113@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
>That said, I agree that vfork is a horrible kludge.  What *should* have
>been coined is the ability to create a process running a new executable
>image in a single system call.  This is the only way the kernel can be
>*assured* (rather than simply having it hinted at) that this process
>creation will not involve the copying of any memory from the parent
>process.  The fork() operation is still interesting and necessary, and
>the exec() operation is still interesting and necessary, but so is the
>create_process() operation.  If you think the operation is not
>interesting and common, note how many zillions of library routines use
>fork() or vfork() immediately followed by exec(), and provoke the kernel
>into doing all sorts of unnecessary work, even if that kernel implements
>copy-on-demand.

I will have to go along with Guy on this one.  I have programed on
systems that that use a "creat_process" call and it is the most complex
system call in the whole system.  I have also scanned the Unix sources
and I have NOT found many uses of "fork" immediately followed by exec.
There is almost always some intermediate code between the two.

Let's take the case of csh, the reason vfork was created.  At the
minimum the csh will change the process group of the new process.  It
will also frequently have to close and open files.  Other programs "su"
have to deal with changes to the real and effective user and group IDs.
A more complete list would include:

	files				resource limits (CPU and memory)
	environment			umask
	priority			alarms
	signals				real and effective UID and GID
	process group			directory

I have probably missed some.  One could make a case for a
"create_process" with limited capabilities for optimizing the most
common case.  Except that the most common case is the most complex
one.  What options do you pass to the "create_process" call to tell it
that fd 1 should be closed and replaced by a pipe shared with the
parent?

Whatever features you decide not to include will be the ones most
desired by somebody else.  And, just when you think you have all
possible options built into your "create_process" call, someone will add
a new process characteristic.  You will then be faced with the prospect
of how to extend the "create_process" call to include the new options.
And of course you have to do this in a way that will be compatible with
old programs!

After looking at the parameters of "create_process" and the extended
parameters, and the optional extended extended parameters I considered
the fork exec of Unix a much cleaner and more elegant solution.

					Jerry Aguirre

nate@altos86.UUCP (Nathaniel Ingersoll) (06/30/87)

In article <113@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
[deleted]
>The counterargument is that each system call should do only one thing,
>and they should be combined to make more complicated operations.  In
>this sense, I agree that only fork() and exec() are needed.  But
>engineers don't build out of nand-gates only, though that is all that is
>logically necessary.  They use gates that more clearly convey intent,
>and thus can gain significant efficency.  Similarly, create_process()
>guarantees the kernel important information about the programmer's
>intent that combinations of fork() and exec() do not, and in this case I
>think the practical benefits of create_process() outweigh the
>theoretical benefits of a "pure" "simple" set of system calls.
>...
>Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

I have seen, on what seemed to be an extended port of BSD 4.2 by Ridge,
a system call called spawn(), which took arguments like execve(),
if my memory serves me correctly.  The idea was that it internally
	fork()
	execve(...args...)
and therefore didn't have to bother with process copying.
Anyone else seen this?

 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<	Nathaniel Ingersoll				>
<	Altos Computer Systems				>
 vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

blarson@castor.usc.edu (Bob Larson) (06/30/87)

In article <4146@teddy.UUCP> jpn@teddy.UUCP (John P. Nelson) writes:
>The situations are NOT analogous.  One of the most common operations
>done between an fork and an exec is the modifications of the file
>descriptors.  Tell me, with create_process, just how would you create
>an inter-process pipe?  The standard code is:
>
>    pipe(fds)
>    if (fork() == 0)
>	{
>	dup2(fds[1], 1);
>	close(fds[0]);
>	close(fds[1]);
>	exec(...);
>	}
>    close(fds[0]);

On os9, which has the create_process os9fork() call rather than a unix-like
fork (error checking omited for simplicity):

pipe = open("/pipe", S_IREAD | S_IWRITE);
temp = dup(1);
close(1);
dup(pipe);
os9fork(...);
close(1);
dup(temp);
close(temp);

Not much harder than on on unix.
Bob Larson		Arpa: Blarson@Ecla.Usc.Edu
Uucp: {sdcrdcf,seismo!cit-vax}!oberon!castor!blarson
"How well do we use our freedom to choose the illusions we create?" -- Timbuk3

chris@mimsy.UUCP (Chris Torek) (07/01/87)

>>guy%gorodish@Sun.COM (Guy Harris)
>>The only remaining reason to use vfork is that one has written ugly
>>and brain-damaged code that depends on the semantics of "vfork".

In article <113@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
>But fork() can *never* be as efficent as vfork(), and sometimes this
>efficency is crucial.

I disagree with the first part of this statement.  If you wish to
claim that on a Vax or other conventional two-level page table
architecture, fork() cannot be as efficient as vfork(), *that* I
can believe.  On the MIPS R2000, I think a copy-on-write fork()
could be just as efficient.

>Even if you can create copy-on-demand during fork(), the database
>needed to keep track of these pages consumes kernel (possibly virtual)
>memory space, and the creation and upkeep of this data consumes
>kernel CPU time.

What database?  Obviously you are considering some particular
implementation.  There are no doubt others, in which this operation
is almost free---costing about the same as vfork().

>The vfork() is hinting to the kernel that an exec() is about to
>occur, and therefore the kernel is well-advised not to invest much
>in the correct copy of the address space.

True; but one could consider *all* forks a hint that an exec() is
soon to occur, and arrange not to run the parent for several
milliseconds while the child finishes its task and exec()s.  In
effect, you would be making all forks vforks, since vfork really
works by suspending the parent, but you would do it without the
unintentionally shared memory.  (Vfork also avoids copying both
pages and PTEs, whereas even copy-on-write fork must copy PTEs.
But who says machines even *have* PTEs?)

>That said, I agree that vfork is a horrible kludge.  What *should* have
>been coined is the ability to create a process running a new executable
>image in a single system call.

As others have said, the big problem here is the need to alter some
of the per-process information before running the new image.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

throopw@xyzzy.UUCP (Wayne A. Throop) (07/02/87)

> guy%gorodish@Sun.COM (Guy Harris)
>> throopw@xyzzy.UUCP (Wayne Throop)

>> But fork() can *never* be as efficent as vfork(), and sometimes this
>> efficency is crucial.
> Yes, there is a savings if you can avoid copying the VM data
> structures, but this savings will be less than the savings from not
> copying the pages themselves.  I'm not convinced that this savings
> will necessarily be enough to justify "vfork".

I wish to make clear that I'm not convinced of this either.  Rather than
defending vfork, I was attempting to suggest that the alternative of a
create_process() operation was preferable.  The justification for vfork
is loosely that the fork of a command processor to create a child
process is most often followed immediately by an exec, and thus a
brain-damaged fork will do just fine for these cases.  My answer is that
it is better to glue the two together so that the brain-damage cannot
possibly bite anyone.

Guy does point out an interesting thing about the "gap" between the fork
and the exec, however:

> If the program to be run in the new process is not to inherit its set
> of open files from its parent, the child process has to rearrange the
> file descriptors before doing an "exec".

Actually, this can all be done in the parent, for most common cases.
The point is that create_process() would act like exec() in that the
child process would close descriptors marked for close-on-exec, and most
file-descriptor-twiddling is reversible, and hence *can* (at some quite
small cost) be done in the parent and then reversed after the
create_process().  Thus, the alternative of making the create_process()
have every bell and whistle for file control duplicated as part of the
call is not really necessary.  And in those cases where it cannot be
done in the parent because of the complication of the
inter-fork()-exec() processing, well... you'll just have to pay the
price of a fork, won't you?

Many may be skeptical that the processing can be done in the parent.  I
can't afford this skepticism, since I participlated in coding many of
the common cases with the file manipulation done in the parent process.
In particular, in popen() and similar library routines, and in the two
shells.  The shells, of course, are the most difficult, and try to
squeeze an indecent amount of processing into the space between the
fork() and the exec(), which is probably why berkeley implementors chose
to do vfork() rather than grit their teeth and gird their loins and
perform all *kinds* of mental preparation via divers asceticisms and go
in there and *fix* *the* *blasted* *shells*.

I sympathize with this decision, but I regret the outcome, which is
unclean vfork() instead of relatively (I emphasize: *relatively*) clean
create_process().

   (I realize that making changes in the parent and then reversing them
    opens a small window of vulnerability where asynchronous events can
    find the process with its pants down, but *that* is just a bug in
    the way asynchronous events (signals et al) are specified to work in
    Unix.  But that's another story.)

--
You find sometimes that a Thing which seemed very
Thingish inside you is quite different when it gets
into the open and has other people looking at it.
                                --- A. A. Milne, Winnie-the-Pooh.
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw

jerry@oliveb.UUCP (Jerry F Aguirre) (07/03/87)

In article <3768@spool.WISC.EDU> lm@cottage.WISC.EDU (Larry McVoy) writes:
>	So what's the big deal, Guy?  Obviously, csh will have to be fixed
>	when they throw out vfork().  But it won't be hard - they'll probably
>	have shared memory by then and people can do it that way.  Whatever
>	fix is used for csh can also be applied to similar programs.  So,
>	I say - use vfork() anyway you like, just be prepared to support
>	new VM models.  I don't see a big problem.  I mean, is all of
>	Berkeley running around chewing their nails over this?  Then
>	why are we?

I think what Guy is complaining about is that such code will not run on
a port of Unix that implements vfork in a different way.  This could be
either a new (4.4) version of BSD Unix or a port of the existing
versions to a new architecture.

Guy is posting from Sun and they are the ones who are always having
problems with null pointer dereferencing.  Somebody writes code that
runs fine on a Vax but core dumps on a sun.  The customer's response is
that Sun does not have a good port because the software ran perfectly on
a Vax.  Sun responds that the code is broken but the Vax just didn't
catch it.  Nobody is happy but DEC.

If someone implements a copy on write version of fork for their port of
4.[23] Unix and makes vfork the same as fork then they will be faced
with a number of programs that don't work correctly.  First off, the
csh.  Naturally they would like to avoid this.

My opinion is that they shouldn't have a vfork unless they can implement
it in a way that is compatible.  The memory sharing characteristic is a
documented and demonstrably used feature of vfork.  Either make a
separate vfork call that does share memory, wait the parent until exec,
etc. or don't claim to have vfork.

It was my understanding that, after a COW fork was implemented, vfork
would disappear, not be maintained as an alternate name for fork.

					Jerry Aguirre

guy%gorodish@Sun.COM (Guy Harris) (07/03/87)

> Guy is posting from Sun and they are the ones who are always having
> problems with null pointer dereferencing.  Somebody writes code that
> runs fine on a Vax but core dumps on a sun.  The customer's response is
> that Sun does not have a good port because the software ran perfectly on
> a Vax.  Sun responds that the code is broken but the Vax just didn't
> catch it.  Nobody is happy but DEC.

Plenty of other people have these problems as well.  Code that makes
a lot of invalid assumptions will run "perfectly" (or, at least, run
without any *obvious* errors; there have been postings in comp.lang.c
that indicate that some such programs do *not* run fine, they just
don't drop core) on a VAX (running one of the common versions of VAX
UNIX; a version done inside BTL disallowed null pointer
dereferencing, and VMS does also) and blow up on any of a number of
machines out there.

The only way to get a machine that will run all the code that runs on
your current VAX is to get another VAX of the same sort.  No, just
buying another VAX isn't good enough.  Take a look at the "comet
sucks" comment in the VAX 4BSD "doprnt.c" (which, despite the ".c"
suffix, is assembler code).  That was a case where the VAX
architecture manual said "don't do this" but somebody went ahead and
did it anyway, and sure enough it didn't work when it ran on a 750.

When a document says "don't do this", like the "vfork" manual page
does, you should take it seriously unless you have an EXTREMELY good
reason not to and are prepared to take the consequences.  In the case
of null pointers, K&R says that null pointers are "distinguishable
from a pointer to any object", which means there is no guarantee what
you get when you dereference one; this should at least act as a
suggestion not to use pointers if they might be NULL without checking
first.  (Fortunately, ANSI C is a bit more firm on this point, for
the benefit of people who don't get the hint.)  You may get a null
string, you may get "f(", you may get something with "p&P6" in it (or
whatever the PDP-11 UNIX C implementation stuffed down at location
0), or you may get a memory fault.

The point here is that some of us have learned that "this program
works on machine X with C compiler Y with version Z of operating
system W under the circumstances we tried it on" is very different
from "this program is correct", or even "this program is reasonably
close to correct".  It is extremely galling when developers blame
*their* bugs on the vendor of a system just because that system
doesn't have all the implementation quirks of the system they were
using before: it's not (little|big)-endian, it doesn't have a zero
byte at location zero, it doesn't allow odd-boundary references to
datatypes longer than 1 byte, it doesn't have _NFILE in <stdio.h>,
etc., etc., etc..  They *could* have gotten it right, but didn't.

> My opinion is that they shouldn't have a vfork unless they can implement
> it in a way that is compatible.  The memory sharing characteristic is a
> documented and demonstrably used feature of vfork.

It is also a characteristic that the manual specifically says should
NOT be used.

> It was my understanding that, after a COW fork was implemented, vfork
> would disappear, not be maintained as an alternate name for fork.

I quote from the manual page:

	This system call will be eliminated when proper system sharing
	mechanisms are implemented.  Users should not depend on the memory
	sharing semantics of "vfork" as it will, in that case, be made
	synonymous to "fork".

This reads as if it were saying that the *mechanism* that implements
"vfork" will go away, but that the *interface* will remain as a
synonym for "fork", so that correctly-written programs will still
work.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

allbery@ncoast.UUCP (Brandon Allbery) (07/03/87)

As quoted from <1028@bloom-beacon.MIT.EDU> by tytso@athena.mit.edu (Theodore Y. Ts'o):
+---------------
| 2)  The man page implies that future versions of *BSD* may change vfork.
| Nowhere in the man page does it say that it is IMPLEMENTATION
| dependant.
+---------------

Nowhere does it say that it is VERSION dependent either, as you assert.  If
some machine implements copy-on-write, that implementation is assured by the
man page to be able to make vfork() == fork().

+---------------
| 3)  Since the man page specifcally goes into painful detail how vfork
| works, the schemamtics of vfork have become part of the BSD 4.3 system
| interface.  Any implementation that changes the meaning of vfork is not
| "FULL" BSD 4.3. 
+---------------

If an early version of a system call has a bug which is documented, that
bug becomes part of the interface and may not be fixed in an update, eh?
Plexus documents late-found bugs in the release notes; this OBVIOUSLY (by
your reasoning) casts them in stone and makes them wholly unfixable.  At
this point, if Plexus did things that way, I would start looking for another
computer company.  (Thank the Witness, they don't!)

Should copy-on-write then require a wfork() call?  --and if it has semantics
that are subject to change, the change should be made into zfork() for the
people who don't pay attention to its being listed as subject to change?
Sure.  Why don't we change all the existing system calls to V6 compatible and
add new ones for the BSD (or SV or etc.) features?  That way we make all the
people who write programs that depend on V6 semantics happy.

Nonsense.  "Let's halt progress or make it painful, that way we can hide our
heads in the sand when it happens."  Do it elsewhere; *I* won't put up with
it.

Also -- just because a system program uses a system call in a way which is
frowned upon does NOT make that usage correct.  If a program uses a feature
in a way that is documented as not being correct, EVEN IF THAT PROGRAM IS
WRITTEN BY THE IMPLEMENTORS OF THE FEATURE, that program is wrong.

The fact that vfork() was developed specifivally for csh is irrelevant; the
manual page released to the public makes it clear that it is now a general
feature.  Again, doing otherwise gets ridiculous -- "ok, let's add cshfork()
and cshexec() and telnetselect() and myprogramread() and ... system calls".
The fact is that vfork, whatever its origins, was made GENERAL.  Otherwise
it would be named csh_only_fork() or something; and as I said above, that
just isn't right.  Adding a new system call should only be done if it's
possible to make the system call general; adding a system call specifically
for a single program's use is wasteful.

++Brandon
-- 
       ---- Moderator for comp.sources.misc and comp.binaries.ibm.pc ----
Brandon S. Allbery	<BACKBONE>!cbosgd!hal!ncoast!allbery ('til Aug. 1)
aXcess Company		{ames,mit-eddie,harvard,talcott}!necntc!ncoast!allbery
6615 Center St. #A1-105	{well,sun,pyramid,ihnp4}!hoptoad!ncoast!allbery
Mentor, OH 44060-4101	necntc!ncoast!allbery@harvard.HARVARD.EDU (Internet)
+01 216 974 9210	ncoast!allbery@CWRU.EDU (CSnet -- if you dare)
NCOAST ADMIN GROUP	Brandon Allbery on 157/504 (Fidonet/Matrix/whatever)
* ncoast -- Public Access UN*X -- (216) 781-6201, 24 hrs., 300/1200/2400 baud *
 * ncoast is proud to be carrying alt.all -- contact me for more information *

jpn@teddy.UUCP (John P. Nelson) (07/06/87)

>On os9, which has the create_process os9fork() call rather than a unix-like
>fork (error checking omited for simplicity):
>
>pipe = open("/pipe", S_IREAD | S_IWRITE);
>temp = dup(1);
>close(1);
>dup(pipe);
>os9fork(...);
>close(1);
>dup(temp);
>close(temp);

But this leaves extra file descriptors open in the child task!  By my
calculation, extra descriptors in the child task are "pipe", and
"temp".  You really want to CLOSE those descriptors in the child task,
but not in the parent task.

Obviously, there can be workarounds:  CLOSE_ON_EXEC information on a
per-descriptor basis, or a convention in all tasks to close all
descriptors above 2 before calling main().  The fundamental point is
unchanged, however, and that is that there is often a need to do some
extra operations between the logical "fork" into two processes, and
the "exec" of a new program image.

blarson@castor.usc.edu (Bob Larson) (07/08/87)

In article <4167@teddy.UUCP> jpn@teddy.UUCP (John P. Nelson) writes:
>>On os9, which has the create_process os9fork() call rather than a unix-like
>>fork (error checking omited for simplicity):
[...]
>But this leaves extra file descriptors open in the child task!  By my
>calculation, extra descriptors in the child task are "pipe", and
>"temp".  You really want to CLOSE those descriptors in the child task,
>but not in the parent task.

No it doesn't.  Os9fork only passes file descriptors 0, 1 and 2.
There is an os9forkc call that allows passing a specified number of
file descriptors.

>Obviously, there can be workarounds:  CLOSE_ON_EXEC information on a
>per-descriptor basis, or a convention in all tasks to close all
>descriptors above 2 before calling main().  The fundamental point is
>unchanged, however, and that is that there is often a need to do some
>extra operations between the logical "fork" into two processes, and
>the "exec" of a new program image.

I have not found such a NEED on os9.  It would make converting unix
programs easier.  (It would require extra hardware to implement a
unix-style fork call.)
Bob Larson		Arpa: Blarson@Ecla.Usc.Edu
Uucp: {sdcrdcf,seismo!cit-vax}!oberon!castor!blarson
"How well do we use our freedom to choose the illusions we create?" -- Timbuk3

cudcv@daisy.warwick.ac.uk (Rob McMahon) (07/14/87)

In article <113@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
>If you think the operation is not
>interesting and common, note how many zillions of library routines use
>fork() or vfork() immediately followed by exec(), and provoke the kernel
>into doing all sorts of unnecessary work, even if that kernel implements
>copy-on-demand.

Searching through the sources yields

	libc/gen/popen
	     .../system
	libU77/chmod

popen needs to re-arrange all its file descriptors, so that leaves
system, and Fortran's chmod.

>
>I think it is clear that there "ought" to be a create_process(), despite
>the fact that it can be created out of fork() followed by exec(),
>because despite all tricks, fork() needs to get a process memory image
>from somewhere, and this will always come at some cost.
>

But this create_process() is going to have to let you rearrange file
descriptors, and probably catch signals to be of any real use.  I can
just imagine the interface---I think I'd rather have fork/exec and make
fork more efficient.

Rob

-- 
UUCP:   ...!mcvax!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick.daisy       ARPA:   cudcv@daisy.warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England