Subject: Re: popen reentrant (was Re: SA/pthread and vfork)
To: Nathan J. Williams <nathanw@wasabisystems.com>
From: Greywolf <greywolf@starwolf.com>
List: tech-kern
Date: 09/11/2003 18:20:20
Thus spake Nathan J. Williams ("NJW> ") sometime Today...

NJW> "posix_spawn()" is the interface you're looking for, possibly. It's
NJW> somewhat contentious, mostly because it's recognized that it's not
NJW> really as powerful as [v]fork()+exec() in terms of environment and
NJW> file descriptor manipulation in the child, although it tries to cover
NJW> the common cases.

It wasn't something I wanted but I was curious if it existed.

NJW>
NJW> Not really. vfork() is a fork() shortcut for when you want to create a
NJW> new process. Sometimes, even in a threaded program, you really want a
NJW> new process (a different protection domain, different application
NJW> code, etc.) rather than a new thread.

Ahhh, okay.

NJW> > If a process threads itself into, say, four threads, can a thread
NJW> > fork()/exec() without destroying the parent?
NJW>
NJW> Yes. The fork() call is specified (and standardized) in a
NJW> multithreaded process to only have one thread in the child; that
NJW> thread in the child can do a few things and then exec().

Got it.

NJW> > Can a thread create another thread?
NJW>
NJW> I'm not sure what circumstances you're asking about. In an ordinary
NJW> threaded process, any thread can call pthread_create() and create
NJW> another thread; there's no restriction, for example, that only the
NJW> "first" thread create others. However, if you're referring to the
NJW> fork()-in-a-threaded-app situation, one of the restrictions on the
NJW> child process is that it can not make any pthread_* calls until after
NJW> the exec() has occurred (at which point it's free to do everything).

As long as a given thread does not fork(), then, it is free, within system
limits, to create threads which can create more threads which can create
more threads ad nauseum?  Okay.

NJW> > Unless I'm mistaken, vfork() came into being because threading didn't
NJW> > exist at the time.  Had threading been around, I doubt vfork() would ever
NJW> > have been written.
NJW>
NJW> Doubtful. Again, vfork() is a shortcut for the fork()+exec() path, not
NJW> a way to provide concurrency - it's actually less useful for
NJW> concurrency than plain old fork().

I guess the million dollar question for vfork()-in-threaded-app would
be:  How much state is shared between a thread?  Does a thread have the
ability to modify its creator?

[sorry that I'm thread-ignorant.  Is there a Threads for Dummies doc
out there somewhere?  I'm sure it'd be better than me pestering the list
for answers.  All in the name of (self-)education...]

Let me see if I understand this correctly:

P0 creates three threads, C0..C2.

C1 decides it's going to fork something off, so it calls vfork(), closes
a few things and calls exec().

Are C0 and C2 going to block waiting for C1 to exec()?

If C0 and C2 don't block, are they free to create threads while C1 is
busying itself preparing for the exec() or _exit()?

[I kind of thought that the point of threading was to avoid blocking
 on this kind of thing...]

Another question:  vfork() and fork() both state that they create a copy
of the process space; inside a thread, does this mean that they copy the
entire process or just the thread from whence they originate?

If a (v)forked thread doesn't block the entire rest of the process, then
as long as the thread is written to perform the (v)fork() correctly
(i.e. it's programmed to close a few things, ioctl a few things and then
exec()), it doesn't strike me that vfork()-in-a-thread should have
substantially different mechanics than vfork()-in-a-process -- if
a child thread (v)fork()s and the space-sharing is local to that thread,
shouldn't the usual rules apply that you just don't go tweaking anything
in the child's/parent's (now shared) space which would adversely affect
the parent, i.e. "don't call exit(), use _exit()..." et al?

Or am I missing a big piece of the picture (again)?

				--*greywolf;
--
NetBSD. Not Guano.