1

When I run this in gdb the parent hangs at waitpid, and I'm not sure why. The parent is supposed to take arguments from argv and send them to the child via a pipe. Then the parent is supposed to receive the sum of the arguments from the child via it's return. Not sure why it's doing this.

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

static int myPipe[2];

int main(int argc, char **argv)
{
    pid_t pid;
    int value;
    int status;
    // set up pipe

    if(pipe(myPipe))
    {
        printf("pipe error\n");
        return -1;
    }

    // call fork()
    printf("CS201 - Assignment 3 Premium - I. Forgot\n");
    pid = fork();
    if (pid == 0) {
        // -- running in child process --
        int     sum = 0;
        close(myPipe[1]);

        for(int i = argc; i > 1; i--)
        {
            read(myPipe[0], &value, sizeof(value));
            sum += value;
        }

        // Return sum of numbers.
        return sum;
        }
    else {
        // -- running in parent process --
        int sum = 0;
        close(myPipe[0]);

for(int i = argc; i > 1; i--)
        {
            value = atoi(argv[i-1]);
            write(myPipe[0], &value, sizeof(value));
        }
        waitpid(pid, &status, 0);
        sum = status;

        printf("sum = %d\n", sum);
        return 0;
        }
csStudent
  • 128
  • 2
  • 12

1 Answers1

1

You problem is that in the parent, you carefully close myPipe[0], and then mysteriously decide to write to it instead of the still open myPipe[1]. If you error checked your system calls, you'd know that you'd failed to send any data to the child. As it is, the child is still waiting for the data to arrive, and won't exit, and the parent is waiting for the child that won't exit to exit, so you have a deadlock.

I'm using the error reporting functions from stderr.c and stderr.h — the code for which is available from GitHub (https://github.com/jleffler/soq/tree/master/src/libsoq) to report errors (and progress).

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

static int myPipe[2];

int main(int argc, char **argv)
{
    pid_t pid;
    int value;
    int status;
    err_setarg0(argv[0]);
    err_setlogopts(ERR_PID|ERR_MICRO);

    if (pipe(myPipe) != 0)
        err_syserr("pipe failed: ");

    // call fork()
    printf("CS201 - Assignment 3 Premium - I. Forgot\n");
    pid = fork();
    if (pid < 0)
        err_syserr("fork failed: ");
    else if (pid == 0)
    {
        // -- running in child process --
        int sum = 0;
        if (close(myPipe[1]) != 0)
            err_syserr("failed to close write end of pipe in child: ");

        for (int i = argc; i > 1; i--)
        {
            if (read(myPipe[0], &value, sizeof(value)) != sizeof(value))
                err_syserr("failed to read from parent: ");
            sum += value;
        }
        if (close(myPipe[0]) != 0)
            err_syserr("failed to close read end of pipe in child: ");

        err_remark("Exiting: sum = %d\n", sum);
        return sum;
    }
    else
    {
        // -- running in parent process --
        int sum = 0;
        close(myPipe[0]);

        for (int i = argc; i > 1; i--)
        {
            value = atoi(argv[i - 1]);
            err_remark("Writing: %d\n", value);
            if (write(myPipe[1], &value, sizeof(value)) != sizeof(value))
                err_syserr("failed to write to child: ");
        }
        if (waitpid(pid, &status, 0) != pid)
            err_syserr("failed to wait for child %d: ", pid);
        sum = status;

        printf("sum = %d\n", sum);
        if (WIFEXITED(status))
            printf("exit status: %d\n", WEXITSTATUS(status));
        return 0;
    }
}

And example output (source code in fp71.c, program fp71):

$ gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
>     -Wstrict-prototypes fp71.c -o fp71 -L./lib -lsoq 
$ fp71 1 2 4 7
CS201 - Assignment 3 Premium - I. Forgot
fp71: 2017-08-15 20:11:48.453688 - pid=86097: Writing: 7
fp71: 2017-08-15 20:11:48.454267 - pid=86097: Writing: 4
fp71: 2017-08-15 20:11:48.454275 - pid=86097: Writing: 2
fp71: 2017-08-15 20:11:48.454281 - pid=86097: Writing: 1
fp71: 2017-08-15 20:11:48.454348 - pid=86098: Exiting: sum = 14
sum = 3584
exit status: 14
$

The decimal value 3584 corresponds to hexadecimal 0x0E00. If you analzye that with WIFEXITED() and WEXITSTATUS, then that is equivalent to 14, as you'd expect. (See also Exit values bigger than 255 — possible?)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278