Thread View: comp.std.unix
18 messages
18 total messages
Started by Donald Lewine
Thu, 20 Dec 1990 21:13
qfork()
Author: Donald Lewine
Date: Thu, 20 Dec 1990 21:13
Date: Thu, 20 Dec 1990 21:13
33 lines
1733 bytes
1733 bytes
Submitted-by: lewine@cheshirecat.webo.dg.com (Donald Lewine)
[[I hope that this has not been covered in detail on comp.std.unix.
Delivery of the newsgroup has been uneven for the last few weeks.]]
[It's not been so much delivery as posting, due to lessened attention
on my part because of lack of funding, and also because of no snitch
reports. -mod]
Draft 5 of POSIX.1a defines qfork() by saying:
"The qfork() function shall be identical to the fork() function with
the following exception: behavior is undefined if the child process
executes any code between the return from qfork() and the succeeding
call to one of the exec functions or _exit()."
This seems to be a very harsh restriction. The following code seems
like it would be undefined:
status = qfork();
if (status == 0) execve(...);
I would propose replacing the phrase: "executes any code" with "calls
any function defined in this standard or the C standard {8}" I think
that does what you mean.
--------------------------------------------------------------------
Donald A. Lewine (508) 870-9008 Voice
Data General Corporation (508) 366-0750 FAX
4400 Computer Drive. MS D112A
Westboro, MA 01580 U.S.A.
uucp: uunet!dg!lewine Internet: lewine@cheshirecat.webo.dg.com
Volume-Number: Volume 22, Number 35
Re: qfork()
Author: Jason Zions
Date: Mon, 24 Dec 1990 16:57
Date: Mon, 24 Dec 1990 16:57
34 lines
2039 bytes
2039 bytes
Submitted-by: jason@cnd.hp.com (Jason Zions)
>"The qfork() function shall be identical to the fork() function with
> the following exception: behavior is undefined if the child process
> executes any code between the return from qfork() and the succeeding
> call to one of the exec functions or _exit()."
>
>This seems to be a very harsh restriction. The following code seems
>like it would be undefined:
> status = qfork();
> if (status == 0) execve(...);
>
>I would propose replacing the phrase: "executes any code" with "calls
>any function defined in this standard or the C standard {8}" I think
>that does what you mean.
I think that loosens the restriction too much. The intent of the text, I
believe, is that *doing* anything between qfork() and exec*() results in
undefined behavior. Checking a variable doesn't *do* anything in this sense.
The text tries to sidestep the issue of "is qfork() a 4.2BSD-style
share-memory pseudo-fork or is it a real fork or what?" An application which
takes an action after qfork() and before exec*() that depends upon the
implementation of qfork() being any one of those things is inherently
unportable.
Instead of replacing "executes any code", I think you could just add the
phrase "which modifies memory or calls any function" and maintain the
intent. Examining variables doesn't depend upon the virtual memory
relationship between child and parent, but munging a stack for a function
call might behave differently and hence must be rendered undefined.
Jason Zions
Volume-Number: Volume 22, Number 39
Re: qfork()
Author: Paul Eggert
Date: Wed, 26 Dec 1990 21:22
Date: Wed, 26 Dec 1990 21:22
19 lines
1221 bytes
1221 bytes
Submitted-by: eggert@twinsun.uucp (Paul Eggert) jason@cnd.hp.com (Jason Zions) writes: The intent of the [Posix.1a draft 5] text, I believe, is that *doing* anything between qfork() and exec*() [or _exit()] results in undefined behavior. I hope this is not the intent. Current applications often do the following actions between forking and execing in a child process: Redirect file descriptors using open(), close(), dup2(). Call write() and _exit() if the exec*() fails. Change signal handling, uid/gid/pgid/session, working/root directory. Call user-defined functions that modify their local variables. Both fork() and vfork() permit these actions. Why should qfork() prohibit them? Volume-Number: Volume 22, Number 42
Re: qfork()
Author: terri_watson
Date: Wed, 26 Dec 1990 22:42
Date: Wed, 26 Dec 1990 22:42
21 lines
1046 bytes
1046 bytes
Submitted-by: terri_watson@cis.ohio-state.edu Of course assuming that the parent doesn't care about the return value of qfork(), then one could manage to conform to the restrictions by: if (qfork() == 0) exit(execve(...)); or for the truly sick-at-heart: (status = qfork()) ? 1 : exit(execve(...)); (Of course it _could_ be argued that, in the second example, the very assignment of status = qfork() violates the rules, but I thought the humor value was high.) But _I'm_ not writing code like that! <grin> Terri Volume-Number: Volume 22, Number 40
Re: qfork()
Author: Barry Margolin
Date: Wed, 26 Dec 1990 22:54
Date: Wed, 26 Dec 1990 22:54
22 lines
1554 bytes
1554 bytes
Submitted-by: barmar@think.uucp (Barry Margolin)
In article <16213@cs.utexas.edu> jason@cnd.hp.com (Jason Zions) writes:
>Instead of replacing "executes any code", I think you could just add the
>phrase "which modifies memory or calls any function" and maintain the
>intent. Examining variables doesn't depend upon the virtual memory
>relationship between child and parent, but munging a stack for a function
>call might behave differently and hence must be rendered undefined.
Rather than "modifies memory" I suggest it be "modifies any variables" or
something like it that refers to high-level objects created by the C
program. Just examining a variable may modify memory; on a stack machine,
comparing a variable with zero generally requires pushing the variable onto
the stack, and even on a register machine loading the variable into a
register might force the register's old value to be written to memory.
--
Barry Margolin, Thinking Machines Corp.
barmar@think.com
{uunet,harvard}!think!barmar
Volume-Number: Volume 22, Number 41
Re: qfork()
Author: Donald Lewine
Date: Thu, 27 Dec 1990 14:31
Date: Thu, 27 Dec 1990 14:31
46 lines
2826 bytes
2826 bytes
Submitted-by: lewine@cheshirecat.rtp.dg.com (Donald Lewine)
In article <16213@cs.utexas.edu>, jason@cnd.hp.com (Jason Zions) writes:
|>
|> I think that loosens the restriction too much. The intent of the text, I
|> believe, is that *doing* anything between qfork() and exec*() results in
|> undefined behavior. Checking a variable doesn't *do* anything in this sense.
|> The text tries to sidestep the issue of "is qfork() a 4.2BSD-style
|> share-memory pseudo-fork or is it a real fork or what?" An application which
|> takes an action after qfork() and before exec*() that depends upon the
|> implementation of qfork() being any one of those things is inherently
|> unportable.
|>
|> Instead of replacing "executes any code", I think you could just add the
|> phrase "which modifies memory or calls any function" and maintain the
|> intent. Examining variables doesn't depend upon the virtual memory
|> relationship between child and parent, but munging a stack for a function
|> call might behave differently and hence must be rendered undefined.
|>
I think I would vote "NO" on qfork(). I think that there are
two better solutions:
(1) Just use fork() and require the implementation to do it
in an efficient manner.
(2) Add some new functions (fexec() ?) which do the fork() and
exec() in one call. I know that this is not existing practice
but neither was sigemptyset() or tcgetispeed(). This may be
another case where it is better to define a new interface than
to try to describe the existing practice. [[Also, qfork() is
not quite vfork() so it can be shot down on the same basis.]]
As I think about it, (2) is a much nicer solution to the problem
than qfork(). The library can then implement fexecl() as a vfork()
followed by an execl() or a fork() followed by an execl(). The
error handling is clean and the semantics are obvious.
--------------------------------------------------------------------
Donald A. Lewine (508) 870-9008 Voice
Data General Corporation (508) 366-0750 FAX
4400 Computer Drive. MS D112A
Westboro, MA 01580 U.S.A.
uucp: uunet!dg!lewine Internet: lewine@cheshirecat.webo.dg.com
Volume-Number: Volume 22, Number 58
Re: qfork()
Author: Peter da Silva
Date: Thu, 27 Dec 1990 18:56
Date: Thu, 27 Dec 1990 18:56
26 lines
1332 bytes
1332 bytes
Submitted-by: peter@ficc.ferranti.com (Peter da Silva)
In article <16066@cs.utexas.edu> lewine@cheshirecat.webo.dg.com (Donald Lewine) writes:
> I would propose replacing the phrase: "executes any code" with "calls
> any function defined in this standard or the C standard {8}" I think
> that does what you mean.
How about "executes any code that changes the state of the program". So,
for example:
static int child;
child = 0;
if(qfork() == 0) {
child = 1;
exec...;
}
At this point, unless I'm confused about legal interpretations of "qfork()",
the value of "child" is indeterminate.
--
Peter da Silva. `-_-' "Eat hot digital death, mainframe scum!"
+1 713 274 5180. 'U` -- Attack of the Killer Micros.
peter@ferranti.com
Volume-Number: Volume 22, Number 43
Re: qfork()
Author: marc
Date: Fri, 28 Dec 1990 14:24
Date: Fri, 28 Dec 1990 14:24
26 lines
1597 bytes
1597 bytes
Submitted-by: marc@arnor.uucp It would be useful to know why the function is being proposed. One assumes an efficiency improvement, which implies that the specifiers have an implementation in mind. Also, it should be remembered that unix systems don't execute C - they execute machine instructions generated by the C compiler. So it is necessary to specify the behavior in machine terms if the compiler writers are going to comply. In particular, there is nothing to prevent the compiler from moving certain computations to the space between the qfork and the exec! Does a compiler need to recognize qfork and exec as special? Finally - if the intent is to "bundle" fork and exec together, assuming only that the fork succeeds, would it not be better to propose fexec* - a set of exec calls which fork first? Of course, this makes it absolutely clear that nothing can happen between fork and exec. If the combined function is then deemed useless, how can the qfork/exec idiom be better? -- Marc Auslander <marc@ibm.com> Volume-Number: Volume 22, Number 44
Re: qfork()
Author: John F Haugh II
Date: Fri, 28 Dec 1990 20:54
Date: Fri, 28 Dec 1990 20:54
24 lines
1695 bytes
1695 bytes
Submitted-by: jfh@rpp386.cactus.org (John F Haugh II) In article <16271@cs.utexas.edu> peter@ficc.ferranti.com (Peter da Silva) writes: >How about "executes any code that changes the state of the program". So, >for example: executing =any= code changes the state of the program. that's the whole problem with this restriction - how much code is too much. >At this point, unless I'm confused about legal interpretations of "qfork()", >the value of "child" is indeterminate. what is probably needed is a "spawn()" function (god, i never thought i'd advocate such a critter) which can be responsible for understanding the legalese. if the only thing you can do after "qfork()" is "exec()", why not merge the two steps into a single function? sounds like the only way to get it right anyhow. -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org "While you are here, your wives and girlfriends are dating handsome American movie and TV stars. Stars like Tom Selleck, Bruce Willis, and Bart Simpson." Volume-Number: Volume 22, Number 47
Re: qfork() (The Spawn of spawn())
Author: Peter da Silva
Date: Sun, 30 Dec 1990 03:11
Date: Sun, 30 Dec 1990 03:11
27 lines
1857 bytes
1857 bytes
Submitted-by: peter@ficc.ferranti.com (Peter da Silva) In article <16307@cs.utexas.edu> jfh@rpp386.cactus.org (John F Haugh II) writes: > what is probably needed is a "spawn()" function (god, i never thought i'd > advocate such a critter) which can be responsible for understanding the > legalese. Wow, this is the same man who ever so politely flamed me for daring to make such a suggestion. fork can be implemented on a large number of O/Ses, but it's rather expensive. If the POSIX standard includes something like a spawn(), that'll sure increase the efficiency of a lot of POSIX software on systems that have been shoehorned into the model. Yes, fork() is a cleaner method of creating new processes. Yes, it takes a fairly complex calling sequence to get spawn() to have anything like the functionality of fork()...exec(). But I think it'd be worthwhile to let a little heresy in in exchange for making POSIX more palatable to folks in poorer environments. The few cases where spawn() won't fit would usually be better addressed by something like threads anyway... -- Peter da Silva. `-_-' "Eat hot digital death, mainframe scum!" +1 713 274 5180. 'U` -- Attack of the Killer Micros. peter@ferranti.com Volume-Number: Volume 22, Number 48
Re: qfork()
Author: Dave Mason
Date: Sun, 30 Dec 1990 16:17
Date: Sun, 30 Dec 1990 16:17
44 lines
2656 bytes
2656 bytes
Submitted-by: mason@tmsoft.uucp (Dave Mason)
In article <16307@cs.utexas.edu> jfh@rpp386.cactus.org (John F Haugh II) writes:
>Submitted-by: jfh@rpp386.cactus.org (John F Haugh II)
>In article <16271@cs.utexas.edu> peter@ficc.ferranti.com (Peter da Silva) writes:
>>How about "executes any code that changes the state of the program". So,
>>for example:
>executing =any= code changes the state of the program. that's the whole
>problem with this restriction - how much code is too much.
The real requirement is presumably: ``Must not execute any code that
changes MEMORY.'' As both the parent and child have their own register
sets. Now, expressing that in a high-level way that is portable may
be quite a trick. (Think of SPARC vs. 386 vs. HP/3000!)
>>At this point, unless I'm confused about legal interpretations of "qfork()",
>>the value of "child" is indeterminate.
Not if it's a register variable.
>what is probably needed is a "spawn()" function (god, i never thought i'd
>advocate such a critter) which can be responsible for understanding the
>legalese. if the only thing you can do after "qfork()" is "exec()", why
>not merge the two steps into a single function? sounds like the only way
>to get it right anyhow.
Not really. Assuming qfork in the parent can make sure there is
nothing on its stack (that it needs to retrieve later) before it
executes the system call instruction, and the child doesn't do
anything except:
a) make system calls that change its KERNEL state (open files, UID, etc.)
b) change register variables
qfork can do everything useful that vfork can. (And because there's no
memory being changed by the child that can be inspected by the parent, a
fork implementation of qfork is still legal.)
(Personally I think the whole vfork/qfork/spawn thing is a horrible hack,
but if we're going to be stuck with it, lets at least do it right!)
--
"Don't break it if you can't fix it." ../Dave Mason
<mason%tmsoft@cs.toronto.edu>
Volume-Number: Volume 22, Number 49
Re: qfork()
Author: John F Haugh II
Date: Wed, 02 Jan 1991 13:17
Date: Wed, 02 Jan 1991 13:17
21 lines
1703 bytes
1703 bytes
Submitted-by: jfh@rpp386.cactus.org (John F Haugh II) In article <16370@cs.utexas.edu> mason@tmsoft.uucp (Dave Mason) writes: >The real requirement is presumably: ``Must not execute any code that >changes MEMORY.'' As both the parent and child have their own register >sets. Now, expressing that in a high-level way that is portable may >be quite a trick. (Think of SPARC vs. 386 vs. HP/3000!) Yes, that is the essence of the problem - there are CPUs out there which have a very small number of CPU registers (perhaps only two or three) available to the user. As I recall, the TI 9900 has one register which points to a location in memory where the rest of the "registers" exist, and of course older HP CPU's have their own ideas about where data is stored. -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org "While you are here, your wives and girlfriends are dating handsome American movie and TV stars. Stars like Tom Selleck, Bruce Willis, and Bart Simpson." Volume-Number: Volume 22, Number 53
Re: qfork() (The Spawn of spawn())
Author: Guido van Rossum
Date: Thu, 03 Jan 1991 09:42
Date: Thu, 03 Jan 1991 09:42
66 lines
3806 bytes
3806 bytes
Submitted-by: guido@cwi.nl (Guido van Rossum) peter@ficc.ferranti.com (Peter da Silva) writes: >Yes, fork() is a cleaner method of creating new processes. Yes, it takes >a fairly complex calling sequence to get spawn() to have anything like >the functionality of fork()...exec(). But I think it'd be worthwhile to >let a little heresy in in exchange for making POSIX more palatable to >folks in poorer environments. I know of precedents even in OS'es that support fork(): Amoeba and Topaz support a variant of what you call spawn(). (Note that the spawn() functions found in Microsoft C for MS-DOS emulate either just exec() or fork()+exec()+wait(), which is much less powerful, but all that MS-DOS can support (last time I looked).) Amoeba's UNIX emulation supports fork(), but since Amoeba has no virtual memory (yet), it is fairly expensive. An alternative function is provided, "newproc()", which creates a child process running a different program (and, because it is Amoeba, also running on a different processor, in the average case) just like fork()+exec() would do, only much cheaper since the parent's address space never gets copied. Amoeba's newproc() lets you change the two perhaps most important bits of "kernel state" that programs fiddle between fork() and exec(): the set of signals to be ignored and the set of open file descriptors. The interface lets you specify a bitmask of signals that are to be ignored in the child (or -1 to inherit the parent's ignored signals) and an array of file descriptors which provides a mapping between file descriptors in the parent and in the child (also with an option to inherit all file descriptors from the parent). Amoeba's library functions popen() and system() have been changed to use newproc(), and the shell uses newproc() for most simple program invocations (environment manipulations and a few other things make it fall back on fork()). The performance gain was well worth the hacking. The newproc() interface could also be implemented on UNIX using [v]fork() and exec(), although extreme cases of file descriptor permutations could fail if not enough spare file descriptors were available. The Topaz operating system (an Ultrix clone for Firefly multiprocessors developed at DEC's System Research Centre in Palo Alto) has a similar but more complete feature in its Modula-2+ (and now Modula-3?) version of the OS interface, not because Topaz doesn't have virtual memory (it does), but because the average Modula-2+ binary is several megabytes. In Topaz, you create a descriptor for the new process, which represents its relevant kernel state. The descriptor is initialized to inherit all state from the parent, and you can call library functions that modify various parts of the descriptor; this is the equivalent of what you would do between fork() and exec() in real UNIX. Finally you make a system call that presents the descriptor to the kernel for creation. Yes, it's a bit more tedious, but it has all the required functionality, unlike (it seems to me) the proposed qfork() with its not-well-understood restrictions on modifying memory. --Guido -- Guido van Rossum, CWI, Amsterdam <guido@cwi.nl> "Well I'm a plumber. I can't act." Volume-Number: Volume 22, Number 55
Re: qfork() (The Spawn of spawn())
Author: Lenox H. Brassell
Date: Fri, 04 Jan 1991 18:04
Date: Fri, 04 Jan 1991 18:04
21 lines
1419 bytes
1419 bytes
Submitted-by: lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) In article <16478@cs.utexas.edu>, guido@cwi.nl (Guido van Rossum) writes: > (Note that the > spawn() functions found in Microsoft C for MS-DOS emulate either just > exec() or fork()+exec()+wait(), which is much less powerful, but > all that MS-DOS can support (last time I looked).) > Using Microsoft C under OS/2, you can pass P_NOWAIT as the first argument to the MSC spawn() functions, and the child process will run asynchronously. The spawn() functions return the child process's PID in this case. Although MSC is certainly not a UNIX compiler, this "prior art" might be a good place to start if POSIX needs a "safe" qfork()+exec() service. --lenox (lenox@media-lab.mit.edu) Volume-Number: Volume 22, Number 59
Re: qfork() (The Spawn of spawn())
Author: Peter da Silva
Date: Fri, 04 Jan 1991 19:17
Date: Fri, 04 Jan 1991 19:17
14 lines
1176 bytes
1176 bytes
Submitted-by: peter@ficc.ferranti.com (Peter da Silva) ( Guido lists a couple of systems where a function with spawn() type semantics (create a new process and load a program)... ) Also, most DEC operating systems use this sort of call for process creation. AmigaOS does things in the opposite order: you load a segment and then use CreateProc to start executing it. -- Peter da Silva. `-_-' "Eat hot digital death, mainframe scum!" +1 713 274 5180. 'U` -- Attack of the Killer Micros. peter@ferranti.com Volume-Number: Volume 22, Number 61
Re: qfork() (The Spawn of spawn())
Author: Loren L. Hart
Date: Sat, 05 Jan 1991 00:43
Date: Sat, 05 Jan 1991 00:43
41 lines
2235 bytes
2235 bytes
Submitted-by: loren@Eng.Sun.COM (Loren L. Hart) In article <16478@cs.utexas.edu> guido@cwi.nl (Guido van Rossum) writes: >Submitted-by: guido@cwi.nl (Guido van Rossum) > >peter@ficc.ferranti.com (Peter da Silva) writes: > >>Yes, fork() is a cleaner method of creating new processes. Yes, it takes >>a fairly complex calling sequence to get spawn() to have anything like >>the functionality of fork()...exec(). But I think it'd be worthwhile to >>let a little heresy in in exchange for making POSIX more palatable to >>folks in poorer environments. > >I know of precedents even in OS'es that support fork(): Amoeba and >Topaz support a variant of what you call spawn(). (Note that the >spawn() functions found in Microsoft C for MS-DOS emulate either just >exec() or fork()+exec()+wait(), which is much less powerful, but >all that MS-DOS can support (last time I looked).) The Ada POSIX Draft currently has some sort of spawn command, since fork is not necessicarily safe with respect to Ada Tasks. I don't rember the specific routine, but it is likely to go through some change before the Ada version of the standard is finalized. I would hope that this spawn capability will be merged back into the 1003.1 standard at some point in the future. ------------------------------------------------------------ Mr. Loren L. Hart The Ada Ace Group, Inc. PO Box 36195 San Jose, CA 95158 loren@cup.portal.com -- ----------------------------------------------------------------------------- Loren L. Hart The Ada Ace Group, Inc loren@cup.portal.com P.O. Box 36195 San Jose, CA 95158 Volume-Number: Volume 22, Number 62
Re: qfork()
Author: Doug Gwyn
Date: Mon, 07 Jan 1991 22:15
Date: Mon, 07 Jan 1991 22:15
15 lines
1337 bytes
1337 bytes
Submitted-by: gwyn@smoke.brl.mil (Doug Gwyn) In article <16213@cs.utexas.edu> jason@cnd.hp.com (Jason Zions) writes: >I think that loosens the restriction too much. The intent of the text, I >believe, is that *doing* anything between qfork() and exec*() results in >undefined behavior. Checking a variable doesn't *do* anything in this sense. >The text tries to sidestep the issue of "is qfork() a 4.2BSD-style >share-memory pseudo-fork or is it a real fork or what?" We (IEEE P1003) deliberately omitted vfork() from the POSIX spec because it was not necessary, given a decent implementation of fork(). Why is this notion being reintroduced (quite carelessly so far as I can tell from the quotes so far) for 1003.1a? Volume-Number: Volume 22, Number 66
Re: qfork() (the spawn of Spawn())
Author: Peter da Silva
Date: Mon, 14 Jan 1991 14:19
Date: Mon, 14 Jan 1991 14:19
51 lines
2510 bytes
2510 bytes
Submitted-by: peter@ficc.ferranti.com (Peter da Silva)
In article <16875@cs.utexas.edu> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> We (IEEE P1003) deliberately omitted vfork() from the POSIX spec
> because it was not necessary, given a decent implementation of fork().
POSIX is not supposed to be a standard for UNIX only. In many non-UNIX
environments a "decent implementation of fork" is quite difficult and
may even be impossible. A poor implementation of fork() is likely to
clobber performance, given how common it is in UNIX code.
I suspect that in practice most implementations will use an efficient
call in the internals of system() and similar library routines. Either
direct spawns or an implementatio of qfork that looks something like:
qfork()
{
Save stack context.
Vector open(), exit(), etc to pseudo routines that
save flags (either adjust jump table or set
a flag that tells open we're "in a qchild".
Return 0;
}
qopen() /* new version of open */
{
open file, save descriptor
}
...
qexec() /* new version of exec */
{
call spawn, passing it the info for the new execution
environment (juggling fds, signals, etc).
Return execution environment to the one set up back
at the qfork (juggle fds, etc)
longjump back to saved stack context, returning child pid.
}
This gets around the cost of creating a new execution context that will
simply be juggled briefly and discarded.
Something like this will be needed to get decent performance out of systems
like VMS where creating a new process is quite expensive. Why not standardise
this so portable programs can take advantage of it?
--
Peter da Silva. `-_-' "Have you hugged your wolf today?"
+1 713 274 5180. 'U`
peter@ferranti.com
Volume-Number: Volume 22, Number 68
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads