Hello!

I was searching for a detailed overview about what exactly is allowed
when vfork is used.  I could find only some rough overview, but neither
uclinux.org nor ucdot.org seem to have a detailed description.  Even
google was of no help.  So I've decided to create such an overview by
thinking about the problem and writing down my thoughts.

My first draft will probably contain many errors, but I hope, with the
help of this list, we will be able to shake out those errors and create
a faq entry which will help other people to port applications.

Please correct/comment if you find any objections in the description
below.

So here I go:

The POSIX manpage that comes with my suse-10.1 box says that the
client is not allowed to:
 - modify any data except a variable to store vfork()'s return value.
 - return from the function in which vfork() was called.
 - call any other function than _exit() or one of the exec family.

This is a very draconic advice, as (taken by word) it means that the
only valid construct is

  if (!(pid=vfork())) {
    execve (...);
    _exit();
  }

Strictly speaking, in contrast to what the man page says, execve() is
the only member of the exec family that is safe, since everything else
is (probably) part of libc and is prone to modify some data.

Since strictly following the man page leads to such a disappointing
result, it is tempting to think about what would actually happen in
the real world.

The showstopper with the widest consequences is errno.  About every
system call can change errno.  As first resort, this can easily be
worked around by saving/restoring errno.  But on a second thought,
not even this is needed.  By definition, errno (in parent context) is 
only valid if vfork() fails.  But since the child already _is_
executing, there's no way for vfork() to signal an error.  Therefore
the parent is not allowed to check errno and thus we are safe to modify
errno.

Next interesting question is the "call any other function" part.  Why
is this restriction?  A callee should never clobber caller's stack
frame.
In the rest of this discussion I assume that it is safe to call other
functions _if_ they obey the above rules.  (Please correct me if I'm
wrong).  If this assumption is wrong, we are back to the construct shown
above being the only valid construct.  Would some guru please clarify
this question?

There are lots of system calls to retrieve/set administrative data of
the process like getpid/setpid/chdir and lots more.  Such functions
operate on kernel's data structures.  The kernel keeps separate memory
for every process to store this information.  Thus there should be no
problem with such calls _if_ the results of such functions are stored
in separate variables which are not accessed by the parent.

Now let's take a look at things like printf() and friends.  They look
very dangerous at first sight.  But OTOH, they should keep their data
structures consistent.  Real problems are to be expected by fopen/fclose
because they invalidate parent's bookkeeping about which files are open.

malloc/free _can_ be safe, too _if_ _exactly_ the malloc'ed areas are
freed.

A big can of worms seem to be signal handlers.  I can imagine only one
way to get them safe: disable all of them before vfork is called.

_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to