Date: Wed, 07 Apr 1999 21:42:29 -0400 (EDT) From: Simon Shapiro <shimon@simon-shapiro.org> To: Matthew Dillon <dillon@apollo.backplane.com> Cc: freebsd-hackers@FreeBSD.ORG Subject: Re: wait4 - Proof I am stupid Message-ID: <XFMail.990407214229.shimon@simon-shapiro.org> In-Reply-To: <199904080038.RAA07199@apollo.backplane.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On 08-Apr-99 Matthew Dillon wrote:
>:Hi Y'll,
>:
>:Please bear with me:
>:...
>:
>: switch (y = wait4((-1)* my_pgid, &z, NULL)) {
>:...
>:
>:Question: Why? Obviously I am doing something wrong, but what?
>
> wait4 takes four arguments, not three. man wait4.
>
> I also strongly suggest compiling with -Wall so you get
> appropriate
> errors when you forget to include the right header files.
>
> Also, your code flow for fork() is dangerous, even if it is only
> demonstration code :-). When you fork, the child should never
> fall
> through into the parents code... it should _exit(0)
> ( note the underscore ) before then. You also need to make sure
> that
> any FILE buffers are flushed before you fork to avoid a
> double-flush
> ( where both parent and child flush the same buffered data in
> FILEs ).
I know all that, Matt. Thanx! :-)
Here is ``real'' code that compiles cleanly with -Wall. Still does the
wrong thing (for me). The problem I am having, is that wait4() says
there are no processes to wait for, while they are there. for sure.
In the real program, the gandchildren run, do I/O, talk to grandpa over
shared memory, get signals from grandpa, etc. Just grandpa cannot see
them in wait4 :-(
>
>
> fflush(stdout); /* prevent double flush from occuring in child
*/
> fflush(stderr); /* prevent double flush from occuring in child
*/
> if ((pid = fork()) == 0) {
> /* child does something */
> _exit(0);
> }
> if (pid == (pid_t)-1) {
> /* fork error occured */
> exit(1);
> }
> /* parent continues execution */
>
> To wait for the child to exit with wait4():
>
> if (wait4(pid, NULL, 0, NULL) < 0) {
> /* something unexpected happened */
> }
> /* wait complete. child is gone */
>
> If you are interested in using a more portable function, look at
> waitpid() rather then wait4().
>
> if (waitpid(pid, NULL, 0) < 0) {
> /* something unexpected happened */
> }
> /* wait complete. child is gone */
>
> If you want the return code:
>
> int status;
> int return_code;
>
> if (waitpid(pid, &status, 0) < 0) {
> /* something unexpected happened */
> }
> return_code = WEXITSTATUS(status);
>
> See 'man waitpid'.
>
> -Matt
> Matthew Dillon
> <dillon@backplane.com>
>
>:Note: The ``code'' above is illutration only...
>:
>:Sincerely Yours, Shimon@Simon-Shapiro.ORG
>: 770.265.7340
>:Simon Shapiro
>
>
>
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-hackers" in the body of the message
Sincerely Yours, Shimon@Simon-Shapiro.ORG
770.265.7340
Simon Shapiro
Unwritten code has no bugs and executes at twice the speed of mouth
[-- Attachment #2 --]
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/uio.h>
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
extern const char * const sys_errlist[];
extern const int sys_nerr;
int
main(int argc, char **argv)
{
int x =0, a = 0;
pid_t my_pgid = getpgrp();
(void)fprintf(stderr, "grandpa grpid = %d\n", my_pgid);
switch (fork()) {
case 0:
(void)setpgid(getpid(), getpid());
my_pgid = getpgrp();
(void)fprintf(stderr, "son: my_pgid = %d\n", my_pgid);
for (x = 0; x < 10; x++) {
switch (fork()) {
case 0:
/* Go do something useful */
(void)fprintf(stderr,
"grandchild %d pid %d "
"in pgrp %d\n", x, getpid(),
getpgrp());
sleep(60);
exit(0);
break;
case -1:
(void)fprintf(stderr, "failed in line %d\n",
__LINE__);
exit(1);
/* Ooops! */
break;
default:
/* Ignore */
break;
}
}
(void)fprintf(stderr, "son exits\n");
exit(0);
break;;
case -1:
/* Ooops! */
(void)fprintf(stderr, "forking the son failed (%s)\n",
strerror(errno));
exit(1);
break;
default:
/* ignore */
(void)fprintf(stderr, "grandpa continues to wait loop\n");
break;
}
x = 10;
sleep(10);
(void)fprintf(stderr, "before wait loop, x = %d\n", x);
while (x) {
pid_t y;
int z;
(void)fprintf(stderr, "in wait loop (%d), my_pgid = %d\n",
++a, my_pgid);
switch (y = wait4((-1)* my_pgid, &z, 0, NULL)) {
case 0:
/* Never happens */
(void)fprintf(stderr, "wait returned 0\n");
if (a == 20)
exit(2);
break;
case -1:
/* ALWAYS HAPPENS */
(void)fprintf(stderr, "wait failed (%s)\n",
strerror(errno));
if (a == 20)
exit(2);
break;
default:
/* Never happens */
(void)fprintf(stderr, "wait returned %d in pass %d\n",
y, x);
--x;
break;
}
}
return(0);
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.990407214229.shimon>
