How to get return value from child process to parent?
Asked Answered
F

2

7

I'm supposed to return the sum of first 12 terms of Fibonacci series from child process to parent one but instead having 377, parent gets 30976.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    pid_t childpid;
    int i, fib_sum=0, fib1=1, fib2=1, temp, status;

    childpid=fork();

    if(childpid!=0)
    {
        wait(&status);
        fprintf(stderr, "%d\n", status);
    }
    else
    {
        for(i=1; i<=12; i++)
        {
            temp=fib1;
            fib_sum=fib1+fib2;
            fib1=fib_sum;
            fib2=temp;
        }
        fprintf(stderr, "%d\n", fib_sum);
        return fib_sum;
    }
}

What am I doing wrong?

Felike answered 30/3, 2018 at 20:57 Comment(13)
You cannot use the process exit status, because on most systems, it has a very limited range (typically 0 to 127, inclusive). Use a pipe instead.Hexachlorophene
You can't use the child return code to return the value. It gets truncated to 7 bits. You'll need to set up a pipe or have child print value to a file that the parent can then read. Also, to get fib_sum in the parent, it is fib_sum = (status >> 8) & 0x7FConcha
Use a pipe to pass data between the processes.Leadwort
I can't use pipes because this is an exercise for my college class. Is there any other way?Felike
How is it being an exercise stops you from using pipes?Tungstic
if you need to get data from the child, you can use a shared global variable that the child updates, and when the parent detects that the child is completed, it would have stored the sum in the shared global.Corena
How would you share that global variable? @bruceg. He has to make a shared memory.Zandrazandt
I would have the child print the result to stdout, and have the parent invoke the child with popen(), and read the result.Sacrilegious
@TonyTannous he's just forking the same program. he would just declare some shared memory object at the global levelCorena
You can pass an int (or an uintptr_t) using sigqueue() and sigwaitinfo() in POSIXy systems, if a pipe or socket is not allowed.Hexachlorophene
"What am I doing wrong?" you probably did not read the documentation to wait(), did you?Hamulus
From man 2 wait: "WEXITSTATUS(wstatus) returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main()."Hamulus
the exit value allows you only to pass back numbers in the range 0..255.Discernible
A
6

I'm supposed to return the sum of first 12 terms of Fibonacci series from child process to parent one but instead having 377, parent gets 30976.

Process exit status is limited in value, therefore it is not the best way to communicate a value between child and parent.

One of the solution is to pass the calculated value using pipes.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    pid_t childpid;
    int i, fib_sum=0, fib1=1, fib2=1, temp, status;

    int fd[2];
    int val = 0;

    // create pipe descriptors
    pipe(fd);

    childpid = fork();
    if(childpid != 0)  // parent
    {
        close(fd[1]);
        // read the data (blocking operation)
        read(fd[0], &val, sizeof(val));

        printf("Parent received value: %d\n", val);
        // close the read-descriptor
        close(fd[0]);
    }
    else  // child
    {
        // writing only, no need for read-descriptor:
        close(fd[0]);

        for(i=1; i<=12; i++)
        {
            temp = fib1;
            fib_sum = fib1+fib2;
            fib1 = fib_sum;
            fib2 = temp;
        }

        // send the value on the write-descriptor:
        write(fd[1], &fib_sum, sizeof(fib_sum)); 
        printf("Child send value: %d\n", fib_sum);

        // close the write descriptor:
        close(fd[1]);

        return fib_sum;
    }
}

Test:

Child send value: 377                                                                                                                         
Parent received value: 377
Ariella answered 30/3, 2018 at 21:44 Comment(0)
C
3

If you can't use pipes, which would be the optimal solution here, you could save the result to a file that the parent would read from. Pass the name of the file to save the result to from parent to child. In your child process, you would do:

int main(int argc, char *argv[])
{
    int fib_sum=0;
    if (argc <= 1)
    {
        print_usage();
        return 1;
    }
    //... calculate fib_sum
    FILE *f = fopen(argv[1], "w");
    if (f == NULL)
    {
        printf("Error opening file!\n");
        return 1;
    }
    fprintf(f, "%d", fib_sum);
    return 0;
}

Then in your parent process:

int n = 0;
FILE* f;
//... spawn child and wait
FILE *f = fopen(file_name, "r");
fscanf(f, "%d", &n);
Clough answered 30/3, 2018 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.