carver@atmos-modelling.chemistry.cambridge.ac.uk (Glenn Carver) (10/05/90)
I'm having problems trying to get the child control that I need with an application using SunView. The structure of the program comprises main.c which sets up the application window and calls window_main_loop(). Then when the user presses a button on the window, a notify procedure gets called which consists of a loop over roughly 100 iterations. On each pass of the loop, a child is created to perform a small task. The time of the child in relation to the time of each loop pass is small so each child terminates before the next child is created. My problem is that I cannot avoid the maximum process limit. Normally, a wait(2) call would clear the terminated child. However, according to the SunView manual, I cannot do a wait(2) call using SunView but have to register a wait3 event handler via notify_set_wait3_func(). I tried registering the default handler notify_default_wait3() but this did not help. While the program was running, using the ps command still shows child processes that are <exiting>, so that after 30 passes of the loop I have 30 <exiting> children. However, when the loop and my notify proc terminate and control returns to the notifier, the child processes disappear. This suggests that the child processes are not fully 'reaped' until control returns to the notifier. Is there any way out of this? Can I, for example, register my own wait3 event handler which itself calls wait(2), or does this still violate the notify convention. Or alternatively, can I force the notifier to do a wait() whilst still in the loop to remove the child process previously created completely. Please email me directly. I will summarise. All help much appreciated. Currently using SunOS 3.5. Glenn Carver Phone (44-223) 336521 Cambridge University, UK. email: carver@atm.ch.cam.ac.uk
Mark_Weiser.PARC@xerox.com (11/01/90)
The problem is that you have to give control back to the notifier so that it can do the wait for you and reap the children. As long as you are in your loop the notifier cannot do anything. This is a very common problem, and the solution I use is to, rather than loop, schedule myself to run again ASAP and return to the notifier, keeping track of the iterations with a global variable. This problem came up so often that I wrote the following simple routines to make it easier to schedule an arbitrary procedure call in the future: /* * Call procedure f in a little while. */ struct call_wrapper { /* Dynamically allocating a wrapper ensures unique notifier id's. */ void (*f)(); } do_with_delay(f, secs, usecs) void (*f)(); int secs, usecs; { Notify_value do_the_call(); struct call_wrapper *w; struct itimerval timer; /* Sigh, so much work just to wait a bit before starting up. */ timer.it_interval.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_value.tv_usec = usecs; timer.it_value.tv_sec = secs; w = (struct call_wrapper *)calloc(sizeof(struct call_wrapper), 1); w->f = f; notify_set_itimer_func(w, do_the_call, ITIMER_REAL, &timer, NULL); } /* * Wrapper to make sure procedures from do_with_delay return good values * to the notifier. */ Notify_value do_the_call(w, which) struct call_wrapper *w; { (*(w->f))(); free(w); return NOTIFY_DONE; }