Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site houligan.UUCP Path: utzoo!watmath!clyde!cbosgd!ihnp4!mhuxn!mhuxr!ulysses!gamma!epsilon!zeta!sabre!petrus!bellcore!decvax!decwrl!pyramid!pesnta!peora!ucf-cs!novavax!houligan!daemon From: daemon@houligan.UUCP Newsgroups: net.unix-wizards,net.unix Subject: Re: UNIX question Message-ID: <229@houligan.UUCP> Date: Wed, 18-Dec-85 14:20:13 EST Article-I.D.: houligan.229 Posted: Wed Dec 18 14:20:13 1985 Date-Received: Mon, 23-Dec-85 04:22:20 EST Sender: daemon@houligan.UUCP Organization: Gould Electronics, Ft. Lauderdale, Florida. Lines: 69 Xref: watmath net.unix-wizards:16214 net.unix:6695 In <156@uw-june> pjs@uw-june (Philip J. Schneider) writes: > I have a C program which, during the course of its execution, > spawns(forks) child processes. ... Since UNIX only allows one a > certain number of processes at a time, eventually during the course of > execution of the parent I run out of processes. If I temporarily stop > the parent process execution and do a 'ps', the child processes show up > in the list with a 'Z' status. They do not completely disappear until > the parent process exits. > > My question: Is there any way to kill off these zombies so I can get > more processes ? Or, failing that, is there any other > way to do what I want ? > > Philip Schneider > University of Washington Computer Science > pjs@{uw-june.arpa,washington.arpa} > {ihnp4,decvax,cornell}!uw-beaver!uw-june!pjs The problem (and fortunately, the solution) is simple. A process, once terminated, becomes a "zombie" (Z status from "ps") until its parent (as determined by its PPID) "wait"s for it. Thus, it is the parent process' responsibility to "clean up after" its children (kinda like real life, eh?) You can do one of two things, depending on your situtation, to handle this correctly. 1. If the parent process does not have anything better to do while the children are out playing, it can just "wait" for them to finish. 2. You can cause the parent to "double-fork". This will make it a "grand-parent" for a time, just long enough for the "parent" to fork the child, and then terminate (exit). Then, when the "grand-parent" waits for the "parent", it will be VERY quick, and should not impact the "grand-parent" (original spawning process) much, in terms of slowing down the execution. Then, the "child" will become an "orphan", and when it terminates, the system "init" process (PID = 1) will clean up after it. Implementation of the "double-fork" is simple (error detection omitted for clarity). /* grand-parent */ switch (fork()) { /* parent */ case 0: /* parent */ switch (fork()) { /* child */ case 0: /* child */ /* do the "child" part */ /* child */ break; /* parent */ default: /* parent */ exit(0); /* orphan the child */ /* parent */ } /* grand-parent */ default: /* grand-parent */ wait(0); /* wait for "parent" */ /* grand-parent */ } /* grand-parent */ /* proceed with normal processing */ Obviously, the "wait" and "fork" calls need to be checked for errors, and you may want to use "_exit" instead, in the "parent", so it doesn't flush buffers, etc. These are left as exercises for the reader. --tgi while (--tgi) /* my mind continues to decay */ ; /* even though I do nothing.. */ {brl-bmd,ccvaxa,pur-ee,sun}!csd-gould!midas!tgi (Craig Strickland @ Gould) 305/587-2900 x5014 CompuServe: 76545,1007 Source: BDQ615 MCIMail: 272-3350 (echo ".ft B"; echo ".ps 999"; echo "$disclaimer") | troff -t # :-)