Home > Software engineering >  Program with pipes and threads exiting before completion
Program with pipes and threads exiting before completion

Time:02-01

I am writing a c program with threading and pipes. I am implementing a parallelized algorithm and the idea is that I have a main thread that writes data to child threads. The child thread must read this data, process it, and write back the result to the main thread.

I have stripped down a minimal reproducing, compiling version of the core logic of the communication and commented out the places where I have more code. The program runs and exits without typing out complete. Usually, the last value of i that is printed is between 1 and 9 and the program just terminates without saying anything. I would expect the program to run to completion but I am not getting any errors and the program exits gracefully so I am not sure how to debug.

NOTE: Pipes and Pthreads are mandated from somewhere else and are hard requirements. Please don't suggest a solution to use std::thread or just communicate between threads within the same address space.


#include <iostream>
#include "pthread.h"
#include "unistd.h"
#include <vector>

using namespace std;
void* func (void* args)
{
    std::vector<int> v = * (std::vector<int>*)(args);
    auto FH = fdopen(v[0], "r");
    char buffer[1024];
    int buffer_len = 1024;
    while (fgets(buffer, buffer_len, FH))
    {
        std::string x{buffer};
    }
    
    // process the result and return it to the parent
    
    return NULL;
    
    
}

int main()
{
    std::vector<std::vector<int> *> pipes{};
    std::vector<pthread_t *> threads{};
    for (int i=0; i<20; i  )
    {
        std::cout<<i<<std::endl;
        int fd[2];
        if (pipe(fd) < 0)
        {
            std::cout<<"failed"<<std::endl;
            exit(0);
        }
        int fd2[2];
        if (pipe(fd2) < 0)
        {
            std::cout<<"failed"<<std::endl;
            exit(0);
        }
        std::vector<int> *pipe_info = new std::vector<int>{fd[0], fd[1], fd2[0], fd2[1]};
        auto F = fdopen(fd[1], "w");
        pthread_t *thread = new pthread_t;
        threads.push_back(thread);
        pipes.push_back(pipe_info);
        pthread_create(thread, NULL, func, (void*) pipe_info);
        for (int i=0; i<100; i  )
            fprintf(F, "%d", 3);
    }
    
    
    
    // read the data returned from the child threads 
    // using fd2 (indices 2,3) in each pipe in pies.
    // free all allocated memory
    
    
    for (auto thread: threads)
    {
        pthread_join(*thread, NULL);
        delete thread;
    }
    std::cout<<"complete"<<std::endl;

    return 0;
}

CodePudding user response:

You are segfaulting in fgets() because FH is NULL, because fdopen() fails with EINVAL, because you are attempting to fdopen() the write end of a pipe (v[1]) as a readable ("r") stdio stream.

CodePudding user response:

I cannot reproduce the problem, and the symptoms you describe seem improbabe. On my system the program prints all the numbers, and does not terminate, but hangs.

The reason is that pipe() is not a constructor; fdopen() is not a constructor either. The are interfaces, and they wouldn't close by virtue of leaving the scope. You have to close fds and FILEs manually. You don't do it, and the threads patiently wait in fgets for more data or EOF. and until main close the writing end of a pipe, there will be no EOF.

  • Related