Parent,child wait,signal

Hello. I want to make a child do some stuff,wait,then the parent does some stuff and then child does some stuff and waits again.I have made the following but it does not work.Can anybody help me?

    pid1 = fork();
    if (pid1 == -1) 
    { 
        perror("Can't create child\n");
        exit(1);
    }
    else 
        if (pid1 == 0) 
        {
            ppid=getppid();
            sprintf(ppidstr,"%d", ppid);
            if(execl("myprogram.exe","myprogram.exe",ppidstr) == -1)
                fprintf(stderr,"execl Error!\n");
            wait(NULL);//Wait until the parent opens myfifo
           printf("I am back to do some more stuff");
           exit();
        }
        else 
            {
                waitpid(0,NULL,0);//wait for the child's signal
                int fd = open(myfifo, O_WRONLY);
                write(fd, "Hi", sizeof("Hi"));
                    close(fd);
                  waitpid(0,NULL,0);//wait for the child's signal
                printf("My child ended ");
                exit(1);
            }

execl() destroys your current process, replacing itself with whatever you told it to run. If you want it to run a process and return, try system().

Thank you very much for your quick reply. Actually this is not the whole code. I made it just for the occasion. I wanted the process just to run a program.And then i want the program to run until some point the wait and then run the rest of it. Do i need kill and wait for this?

The fifo by itself can do the waiting that you want to do. main tries to open the fifo, main stops running until something else opens the other end of the fifo. child opens the other end, both start running again.

Oh god! Really? This is very helpful!! Thank you very much!!

---------- Post updated at 03:41 PM ---------- Previous update was at 02:52 PM ----------

Are u sure about what you told me? It doesn't work for me...

---------- Post updated at 03:54 PM ---------- Previous update was at 03:41 PM ----------

I want to open the FIFO in the child.Then send something to parent (just to "wake him", so the child waits) Then i want for the parent to send and when he sends i go on int the child's code. I ll show you my code. Maybe someone can help me, thank you

The parent's code

                int fd = open(myfifo, O_RDONLY);
                read(fd, buf, sizeof(buf));
                close(fd);
                   printf("PReceived: %s\n", buf);
                fd = open(myfifo, O_WRONLY);
                write(fd, "Hi", sizeof("Hi"));
                    close(fd);
                wait(NULL);
                printf("Me child ended ");
                exit(1);

And the child's code

    char * myfifo = "/cygdrive/c/a/progsys/tmp",buf[MAX_BUF];
    int ppid=atoi(argv[1]),fd;
    mkfifo(myfifo, 0666);
    printf("Doing stuff");
    fd = open(myfifo, O_WRONLY);
    write(fd, "Hid", sizeof("Hid"));
    close(fd);
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, MAX_BUF);
    printf("CReceived: %s\n", buf);
    close(fd);

In one window I just did:

$ mkfifo xyz
$
$ cat < xyz

It hung just as it should. In a second window I did echo hello > xyz and now the first window looks like:

$ mkfifo xyz
$
$ cat < xyz
hello
$

(Except that I added red tags to show the new lines.)

I'm sorry...i am new, i have no idea what you just told me.I can only work with code,not in UNIX

---------- Post updated at 04:30 PM ---------- Previous update was at 04:00 PM ----------

Corona688 i think you mistook FIFO with pipes...right?

Nope. Look at what I said more closely. I never said anything about writing to the fifo, but what happens when you open it.

Lemme write you a little example.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(void)
{
        pid_t pid;
        int fd;
        mkfifo("./myfifo", 0660);

        pid=fork();
        if(pid == 0)    // child code
        {
                fprintf(stderr, "C\tWaiting 3 seconds\n");
                sleep(3);
                fprintf(stderr, "C\tOpening fifo\n");
                fd=open("./myfifo", O_RDONLY);
                fprintf(stderr, "C\tOpening fifo\n");
                fd=open("./myfifo", O_RDONLY);
                exit(0);
        }
        else if(pid > 0)        // parent code
        {
                fprintf(stderr, "P\tOpening fifo\n");
                fd=open("./myfifo", O_WRONLY);
                fprintf(stderr, "P\tFIFO opened\n");
                exit(0);
        }

        perror("Couldn't fork");
        return(1);
}

The parent creates the fifo, then creates the child, then tries to immediately open the fifo.

The child waits 3 seconds before opening the fifo, forcing the parent to wait 3 seconds as well. The fifo will finish opening only when there's something trying to open both ends.

1 Like

mmm i see...thank you!! i ll find a way to use this.Thank you very much!!

---------- Post updated at 05:27 PM ---------- Previous update was at 05:18 PM ----------

Still...the waiting part doesn't work when it is done by two different programs right?

---------- Post updated at 05:35 PM ---------- Previous update was at 05:27 PM ----------

Let me explain what i mean.I want to make the parent process wait but through a separate program.So...
Parent

        if (pid1 == 0) 
        {
            ppid=getppid();
            sprintf(ppidstr,"%d", ppid);
            if(execl("b.exe","b.exe",ppidstr) == -1)
                fprintf(stderr,"execl Error!\n");
        }
        else 
            {
                fd2 = open(myfifo2, O_RDONLY);
                read(fd2, buf, sizeof(MAX_BUF));
                   printf("PReceived: %s\n", buf);
                printf("My child ended ");
            }

And this is a separate program

int main(int argc, char **argv)
{
    char * myfifo1 = "/cygdrive/c/a/progsys/tmp1",buf[MAX_BUF];
    char * myfifo2 = "/cygdrive/c/a/progsys/tmp2";
    mkfifo(myfifo1, 0666);
    mkfifo(myfifo2, 0666);

    printf("Doing stuff");
    int fd2 = open(myfifo2, O_WRONLY);
    write(fd2, "Hid", sizeof("Hid"));
    int ppid=atoi(argv[1]),fd;
    int fd1 = open(myfifo1, O_RDONLY);

To be more specific, i want the "Doing stuff" to appear first...but it doesn't

there's a reason I was using stderr, printf() is buffered. That printf(), without a newline, doesn't print until your program quits! Especially weird things can happen to printf statements in a fork, too -- if you have text waiting in a buffer like that, it will be printed twice. Try printing to stderr. It prints immediately with no buffer.

Also, try writing hid\n instead of hid. I think fifos and pipes may line-buffer.

OK, i did everything like you said. It worked fine and I can manage two different programs like this. The only program i have is that when i write on the FIFO the other program can't read it immediatelly. I think that the first program doesn't have enough time to write on the FIFO so that the other can read.I had to place a sleep(5) so that it can collect the data properly. Is there a way to lose the sleep?

---------- Post updated at 07:44 PM ---------- Previous update was at 07:07 PM ----------

Also i can only send 3-4 characters through the FIFO, is this normal?

You've only posted extremely incomplete parts of your program so I have no idea what's happening, let alone what's going wrong.

I understand, i will post the important stuff. When i try to execute this fprintf(stderr,"\n!%s!",buf); on the child i only get 3-4 chars. argv is 3 5 6 asdf and i only get 3 5 on the child.
I am grateful for you helping me, i don't want to impose. If you have time please just take a look. Thank you!!

Parent

if (pid == 0) 
        {
   
            if(execl("b.exe","b.exe",NULL) == -1)
                fprintf(stderr,"execl Error!\n");
        }
        else 
            {
                fd = open(myfifo, O_WRONLY);
                   write(fd, data, MAX_BUF);
                printf("Parent ended ");
                close(fd);
                fd = open(myfifo, O_RDONLY);
            }

Child

#define MAX_BUF 5000

int main(int argc, char **argv)
{
    int fd,i,j,iteration=1,lowerBound,upperBound,numPoints;
    char * myfifo = "/cygdrive/c/a/progsys/tmp";
    char buf[MAX_BUF]="",permbuf[MAX_BUF]="",sourcefile[MAX_BUF]="",finalsourcefile[MAX_BUF]="";
    fd = open(myfifo, O_RDONLY);
    sleep(5);
    read(fd, buf, sizeof(MAX_BUF));
    fprintf(stderr,"\n!%s!",buf);

read() isn't a string function. It doesn't give you a null terminator. You have to check its return value to see how much you read, and print it with write() fwrite() or the like.

Your program is still extremely incomplete, so I have no idea what you're writing to the fifo.

Also, I see you're using cygwin, not UNIX, so the behavior of this program may be very suspect in any case. Windows doesn't actually have named pipe files.

So, read takes the bytes partially? i should put more read functions underneath?

It can take bytes partially but I have no idea if that's the case right now because
a) You haven't posted enough of the program
b) You haven't checked read's return value
c) You're feeding the array into printf("%s") which expects strings, even though
c) read doesn't read strings! It puts no null terminator in it for you! Use write or fwrite!

Corona,

Till now i was considering that pipes and fifo are same except the fact that fifo's existence can be control since it has a name and sometimes resides in a file system.

But now i have doubt, is there any other difference between them considering implementation and usage.

This is what i was referring to

Ok i ll send you everything in case you understand what is hhappening. I do everything as i saw it online.I keep getting an Input/Output error on read.

#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <sys/wait.h>
#include  <stdio.h>
#include  <signal.h>
#include  <sys/ipc.h>
#include  <sys/shm.h>
#define MAX_BUF 5000

int main(int argc, char **argv)
{
    pid_t pid;
    int i,fd;
    char buf[MAX_BUF]="",data[MAX_BUF]="";
    char * myfifo = "/cygdrive/c/a/progsys/tmp";
     if (mkfifo(myfifo, 0666) != 0)
        perror("mkfifo() error");
    for(i=1;i<5;i++)
    {
        strcat(data,argv);
        strcat(data," ");    
    }
    fprintf(stderr,"#%s#",data);
    pid = fork();
    if (pid == -1) 
    { 
        perror("Can't create child\n");
        exit(1);
    }
    else 
        if (pid == 0) 
        {
   
            if(execl("b.exe","b.exe",NULL) == -1)
                fprintf(stderr,"execl Error!\n");
        }
        else 
            {
                if(fd = open(myfifo, O_WRONLY)<0)  perror("open() error for read end");
                   if (write(fd, data, strlen(buf))<0);    perror("write() error");
                printf("Parent ended ");
                close(fd);
                fd = open(myfifo, O_RDONLY);
            }
}

Child

#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <sys/wait.h>
#include  <stdio.h>
#include  <signal.h>
#include  <sys/ipc.h>
#include  <sys/shm.h>
#define MAX_BUF 5000

int main(int argc, char **argv)
{
    int fd,i,j,iteration=1,lowerBound,upperBound,numPoints,numread;
    char * myfifo = "/cygdrive/c/a/progsys/tmp";
    char buf[MAX_BUF]="",permbuf[MAX_BUF]="",sourcefile[MAX_BUF]="",finalsourcefile[MAX_BUF]="";
    if (fd = open(myfifo, O_RDONLY)<0) perror("open() error for read end");
    sleep(5);
    if (numread=read(fd, buf, sizeof(MAX_BUF))<0) perror("read ferror for read end");
    buf[numread]='0';
    write (1,buf,numread);
    

Lots of errors.

char * myfifo = "/cygdrive/c/a/progsys/tmp";

I repeat: fifo's might not work on Windows, because windows doesn't even have them. The closest it has is a named pipe that doesn't actually exist as a file anywhere.

You don't actually quit after most errors.

fprintf(stderr,"#%s#\n",data);

Unless you really want to view everything as one giant messy line, you might want to put an \n in things once in a while.

        if (pid == 0) 
        {
   
            if(execl("b.exe","b.exe",NULL) == -1)
                fprintf(stderr,"execl Error!\n");

            exit(1);

Can't forget that. If b.exe fails to run for any reason, the child will keep going!

                   if (write(fd, data, strlen(buf))<0);    perror("write() error");

That extra semicolon means it will always print 'write error', even when there's no write error.

                printf("Parent ended ");
                close(fd);
                fd = open(myfifo, O_RDONLY);

Why is the parent opening the fifo twice? The child doesn't open it twice, the parent will wait forever for something to open it again.

Why do you have your child code in a separate program when you could put it all in one and save yourself a lot of headaches?

buf[numread]='0';

0 is not null, 0 is 0. Try '\0'.

write (1,buf,numread);

...not that you actually need a null terminator any more when you use write(). How about fprintf(stderr, "%d bytes\n", (int)numread); to see how many you actually read?

---------- Post updated at 09:29 AM ---------- Previous update was at 09:19 AM ----------

Lastly: Your main program is writing 0 bytes on purpose because you're checking the length of the wrong buffer -- buf, instead of data.

---------- Post updated at 09:33 AM ---------- Previous update was at 09:29 AM ----------

Also: sizeof(MAX_BUFFER) is probably 4 or 8, not 5000 like you intended. Just MAX_BUFFER is what you want.

---------- Post updated at 09:38 AM ---------- Previous update was at 09:33 AM ----------

Also if(fd = open(myfifo, O_WRONLY)<0) doesn't have enough brackets. fd becomes either 0 or 1 -- which is never the FD of your open fifo! You've been reading from stdin and writing to stdin, not your fifo, I think.

When I correct all that, it works fine, with no sleep().