0

I need to pipe from my read function to my write function. I tested using the command line ./mapstore retrieve ABCD 2>/dev/null | ./mapstore -p ./new_dir/ stream ABCD and this successfully wrote the data into a pipe and stream successfully read the data from the pipe and wrote it to the filesystem.

I would like to do this in C, but I'm having issues. retrieve_data failed: Undefined error: 0 I based my code off what was in this issue Classic C. Using pipes in execvp function, stdin and stdout redirection

#include <unistd.h>
#include <stdlib.h>
#include "mapstore.h"

int main(int argc, char *argv[]) {

    mapstore_ctx ctx;
    if (initialize_mapstore(ctx, NULL) != 0) {
       fprintf(stderr, "Error initializing mapstore\n");
        return 1;
    }

    mapstore_ctx new_ctx;
    if (initialize_mapstore(&new_ctx, NULL) != 0) {
       fprintf(stderr, "Error initializing mapstore\n");
        return 1;
    }

    char *hash = argv[1];
    int des_p[2];
    if(pipe(des_p) == -1) {
      fprintf(stderr, "Failed to create pipe\n");
      status = 1;
      goto end_restructure;
    }
    printf("1\n");

    if(fork() == 0) {
        printf("1a\n");
        close(des_p[0]);       //closing pipe read
        printf("2a\n");
        close(des_p[1]);
        printf("3a\n");
        if ((status = retrieve_data(ctx, des_p[1], hashes[i])) != 0) {
            perror("retrieve_data failed");
            exit(1);
        }
        printf("4a\n");
        exit(0);
    }

    if(fork() == 0) {
        printf("1b\n");
        close(des_p[1]);       //closing pipe write
        printf("2b\n");
        close(des_p[0]);
        printf("3b\n");
        if ((status = store_data(&new_ctx, des_p[0], hashes[i])) != 0) {
            perror("store_data failed");
            exit(1);
        }
        printf("4b\n");
        exit(0);
    }
    printf("2\n");
    close(des_p[0]);
    printf("3\n");
    close(des_p[1]);
    printf("4\n");
    wait(0);
    wait(0);
    return 0;
}

Complete code is available here https://github.com/aleitner/libmapstore/blob/master/src/mapstore.c#L374

  • At first glance, your code looks about right. What issues are you having? – John Bollinger Dec 08 '17 at 21:53
  • When I run the code it will give me something along the lines of `./src/mapstore restructure Hash: 04a672a6eae704366c44d666890e43ad16bad2b9 retrieve_data failed: Undefined error: 0` and then the it will just hang forever until I send a signal to quit – Alexander Leitner Dec 08 '17 at 21:55
  • That error message tells me that your `retrieve_data()` function returned 0, with `errno` having the value 0. Does `retrieve_data()` in fact return 0 on failure, or have you maybe got your logic reversed there? – John Bollinger Dec 08 '17 at 21:59
  • Also, your `store_data()` and `retrieve_data()` functions appear to each take a file descriptor as an argument. If these functions actually use those to read from / write to, then what do you gain by duping the pipe ends onto the standard streams instead of just using the pipe ends directly? – John Bollinger Dec 08 '17 at 22:02
  • A return code of 0 means the functions succeeded. I just assumed it was good practice to dup the pipe. – Alexander Leitner Dec 08 '17 at 22:07
  • So if those functions return 0 on success, then you have indeed reversed the logic around whether they `return status` or whether they call `perror()`. – John Bollinger Dec 08 '17 at 22:08
  • 1
    As for duping the pipe ends, it's better practice to avoid unnecessary operations. Duping the pipe ends is standard practice when you're programmatically redirecting into a program's standard streams, but that's usually accompanied by `exec`ing a different program. You don't appear to need that. – John Bollinger Dec 08 '17 at 22:11
  • Realized I had a typo. I updated the code and this is the results from running with the print statements. `Hash: 04a672a6eae704366c44d666890e43ad16bad2b9 1 1a 2 3 4 2a 3a 1b 2b 3b 4a` after 4a the app hangs – Alexander Leitner Dec 08 '17 at 22:36
  • That's a reasonable debugging technique. I'm sure that you don't need me to tell you that it seems to indicate that your `store_data()` function does not return. In my crystal ball, I see `store_data()` performing at least one read from standard input instead of from the specified file descriptor, but that thing's pretty cloudy these days. More like a snow globe, really. – John Bollinger Dec 08 '17 at 22:39
  • Looks like sqlite is getting an ioerror at some point and then loops forever giving a misuse error over and over again. classic database functionality. I think store_data and read_data are trying to access sqlite at the same time – Alexander Leitner Dec 08 '17 at 22:50
  • It's odd that this problem occurs when I use the pipe in my code, but now when I pipe the output of one function to another via the command line – Alexander Leitner Dec 08 '17 at 23:03

0 Answers0