The discussion about XEmacs blowing with really large mail messages
reminded me of a concern that I had a long time ago about *macs and
subprocesses.
When a UNIX process wants to create a child, it fork()s and exec()s.
The fork() duplicates the parent's address space. This was seen as
silly when 9 times out of 10 the child simply calls exec and thus was
born vfork(). vfork() has this problem, though that the child briefly
runs in the parents address space. The implications of this statement
are serious and have resulted in two things. First, standards authors
have had no choice but to say that you can't guarantee anything aside
from exec() or _exit() will work. Second, application developers have
been bitten by all kinds of nasty bugs and have shied away from vfork.
The net result is that vfork() could probably be removed from the UNIX
ABI and nobody would shed a tear.
However, some processes get ridiculously large. Fork/exec on a >100MB
process can be quite silly... and knowing that there have been some
important bug fixes within Solaris' vfork I decided it was time to
have a second look.
I hacked process-unix.c to use vfork() instead of fork(), built, and
ran. I then loaded up a whole bunch of large files I have kicking
around until I ran out of memory (for those really curious, there's
pmap output at the bottom of this mail). I then started using things
like M-x shell to create subprocesses. I kept going until I exhausted
the per process file descriptor limit. Were my XEmacs using fork(),
those shells would never have gotten started because the calls to
fork() would fail.
So, for those folks playing with 36MB mail attachments for which
mmencode needs to be called as a subprocess, seems like vfork might
not be so bad after all...
Rather than shun vfork, perhaps careful examination and
rationalization of all the code that gets run in the child after the
[v]fork() would be a plan...
Of course, the right answer is for UNIX at large to adopt the Plan 9
rfork()...
Comments?
P.S. I'm going to run with vfork() instead of fork() for a little
while to see if I run into any nasties that weren't uncovered by my
experiment. I'll keep you posted.
-----------
pmap output:
3174: src/xemacs
Address Kbytes Resident Shared Private Permissions Mapped File
00010000 5280 4208 - 4208 read/exec xemacs
00546000 2408 2160 - 2160 read/write/exec xemacs
007A0000 30640 9264 - 9264 read/write/exec [ heap ]
D5C00000 5584 5448 - 5448 read/write [ anon ]
D6400000 10152 9688 - 9688 read/write [ anon ]
D7400000 4936 4888 - 4888 read/write [ anon ]
D7C00000 16344 12696 - 12696 read/write [ anon ]
D9400000 10152 7904 - 7904 read/write [ anon ]
DA400000 7096 6504 - 6504 read/write [ anon ]
DAC00000 11448 8480 - 8480 read/write [ anon ]
DBC00000 7992 7016 - 7016 read/write [ anon ]
DC400000 11448 7952 - 7952 read/write [ anon ]
DD400000 6304 4912 - 4912 read/write [ anon ]
DDC00000 5584 3752 - 3752 read/write [ anon ]
DE400000 4936 3952 - 3952 read/write [ anon ]
DEC00000 4936 3160 - 3160 read/write [ anon ]
DF400000 11448 6560 - 6560 read/write [ anon ]
E0800000 6304 4104 - 4104 read/write [ anon ]
E1000000 4936 2912 - 2912 read/write [ anon ]
E1800000 18400 10472 - 10472 read/write [ anon ]
E2C00000 7096 3408 - 3408 read/write [ anon ]
E3C00000 16344 7024 - 7024 read/write [ anon ]
E4C00000 11448 4840 - 4840 read/write [ anon ]
E5800000 14512 5504 - 5504 read/write [ anon ]
E6800000 16344 5832 - 5832 read/write [ anon ]
E7C00000 10152 4912 - 4912 read/write [ anon ]
E8800000 12888 5320 - 5320 read/write [ anon ]
E9800000 26208 9048 - 9048 read/write [ anon ]
EB400000 26208 8528 - 8528 read/write [ anon ]
ED000000 7096 2200 - 2200 read/write [ anon ]
ED800000 4936 2536 - 2536 read/write [ anon ]
EE000000 33192 7864 - 7864 read/write [ anon ]
F0400000 7096 1776 - 1776 read/write [ anon ]
F0C00000 20704 5552 - 5552 read/write [ anon ]
F2400000 37368 6144 - 6144 read/write [ anon ]
F4C00000 26208 3944 - 3944 read/write [ anon ]
F6C00000 6304 1688 - 1688 read/write [ anon ]
F7400000 5584 3360 - 3360 read/write [ anon ]
F7C00000 26208 6592 - 6592 read/write [ anon ]
F9800000 10152 1144 - 1144 read/write [ anon ]
FA400000 9000 2304 - 2304 read/write [ anon ]
FB000000 5584 1496 - 1496 read/write [ anon ]
FB800000 9000 1400 - 1400 read/write [ anon ]
FC400000 7096 1720 - 1720 read/write [ anon ]
FCC00000 16344 2272 - 2272 read/write [ anon ]
FDC80000 3848 3080 - 3080 read/write [ anon ]
FE080000 3856 352 - 352 read/write [ anon ]
FE700000 720 664 - 664 read/write [ anon ]
FE880000 1032 992 - 992 read/write [ anon ]
FE9B0000 344 336 - 336 read/write [ anon ]
FEA60000 8 8 - 8 read/write [ anon ]
FEA70000 8 8 - 8 read/write [ anon ]
FEA80000 360 344 - 344 read/write [ anon ]
FEAE0000 344 336 - 336 read/write [ anon ]
FEB60000 8 - - - read/write [ anon ]
FEB80000 8 - - - read/write [ anon ]
FEB90000 8 - - - read/write [ anon ]
FEBA0000 8 8 - 8 read/write [ anon ]
FEBB0000 16 16 8 8 read/exec libmp.so.2
FEBC2000 8 8 8 - read/write/exec libmp.so.2
FEBD0000 80 24 16 8 read/exec libICE.so.6
FEBF2000 8 - - - read/write/exec libICE.so.6
FEBF4000 8 - - - read/write/exec [ anon ]
FEC00000 656 608 592 16 read/exec libc.so.1
FECB2000 32 32 - 32 read/write/exec libc.so.1
FECC0000 8 8 - 8 read/write [ anon ]
FECD0000 16 16 8 8 read/exec libc_psr.so.1
FECE0000 40 16 8 8 read/exec libSM.so.6
FECF8000 8 - - - read/write/exec libSM.so.6
FED00000 512 384 368 16 read/exec libnsl.so.1
FED8E000 40 40 - 40 read/write/exec libnsl.so.1
FED98000 32 8 - 8 read/write/exec [ anon ]
FEDB0000 8 8 - 8 read/write/exec [ anon ]
FEDC0000 24 24 16 8 read/exec libgen.so.1
FEDD4000 16 16 - 16 read/write/exec libgen.so.1
FEDE0000 32 32 24 8 read/exec libsocket.so.1
FEDF6000 16 16 - 16 read/write/exec libsocket.so.1
FEE00000 88 72 64 8 read/exec libm.so.1
FEE24000 8 8 8 - read/write/exec libm.so.1
FEE30000 168 72 - 72 read/exec libcurses.so.1
FEE68000 40 8 - 8 read/write/exec libcurses.so.1
FEE72000 8 - - - read/write/exec [ anon ]
FEE80000 8 - - - read/write [ anon ]
FEE90000 448 440 432 8 read/exec libX11.so.4
FEF00000 24 24 - 24 read/write/exec libX11.so.4
FEF10000 336 336 320 16 read/exec libXt.so.4
FEF74000 24 24 - 24 read/write/exec libXt.so.4
FEF7A000 8 8 - 8 read/write/exec [ anon ]
FEF80000 488 112 104 8 read/exec libtt.so.2
FF00A000 48 - - - read/write/exec libtt.so.2
FF020000 80 72 64 8 read/exec libXext.so.0
FF042000 8 8 8 - read/write/exec libXext.so.0
FF050000 8 8 - 8 read/write/exec [ anon ]
FF060000 80 56 48 8 read/exec libXmu.so.4
FF082000 16 16 - 16 read/write/exec libXmu.so.4
FF090000 384 192 160 32 read/exec libDtSvc.so.1
FF0F0000 24 24 - 24 read/write/exec libDtSvc.so.1
FF100000 2032 1160 1048 112 read/exec libXm.so.4
FF30C000 96 88 - 88 read/write/exec libXm.so.4
FF330000 56 8 - 8 read/exec libXpm.so.4.6
FF34C000 8 - - - read/write/exec libXpm.so.4.6
FF360000 160 40 - 40 read/exec libpng.so.2.1.0
FF396000 16 - - - read/write/exec libpng.so.2.1.0
FF3A0000 8 8 - 8 read/exec libdl.so.1
FF3B0000 120 120 112 8 read/exec ld.so.1
FF3DC000 8 8 - 8 read/write/exec ld.so.1
FF3DE000 8 8 - 8 read/write/exec [ anon ]
FFBCC000 144 88 - 88 read/write/exec [ stack ]
-------- ------ ------ ------ ------
total Kb 576464 242832 3416 239416