0

I'm trying to implement a system where arbitrary number of processes would communicate to each other via named pipes. The implementation is in C++ in Windows. However, I'm stuck because the processes seem to be unable to receive messages. I was unable to find a similar question, I apologize if it was already asked. Anyway, here's the code related to handle creation. The idea is that I have n(n=approx 5 or 6) processes and every process has a named pipe for writing (pipesIn) and reading (pipesOut).

pipesIn = std::vector<HANDLE *>();
    pipesOut = std::vector<HANDLE *>();
    this->name = name;
    wchar_t pipeName[20];
    for (int i = 0; i < total; i++) {
        if (i != name) {
            HANDLE hIn;
            swprintf(pipeName, L"\\\\.\\pipe\\Pipe(%d,%d)", name, i);
            do {
                hIn = CreateNamedPipe(pipeName,
                    PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
                    PIPE_WAIT,
                    1,
                    1024 * 16,
                    1024 * 16,
                    NMPWAIT_USE_DEFAULT_WAIT,
                    NULL);
            } while (hIn == INVALID_HANDLE_VALUE);
            pipesIn.push_back(&hIn);
        }
    }

    for (int i = 0; i < total; i++) {
        if (i != name) {
            HANDLE hOut;
            swprintf(pipeName, L"\\\\.\\pipe\\Pipe(%d,%d)", i, name);
            do {
                hOut = CreateFile(pipeName,
                    GENERIC_READ | GENERIC_WRITE,
                    0,
                    NULL,
                    OPEN_EXISTING,
                    0,
                    NULL);
            } while (hOut == INVALID_HANDLE_VALUE);
            pipesOut.push_back(&hOut);
        }
        else {
            pipesIn.push_back(NULL);
            pipesOut.push_back(NULL);
        }
    }

The problem I have is in my receive function. When I call ConnectNamedPipe, result is 0, and GetLastError() returns ERROR_INVALID_HANDLE.

char response[20];
    DWORD dwRead;

    bool recieved = false;
    while (!recieved) {
        bool flag = false;
        for (int i = 0; i < pipesIn.size(); i++) {
            if (name == i) {
                continue;
            }
            if (ConnectNamedPipe(pipesIn.at(i), NULL) != FALSE) {
                while (ReadFile(*(pipesIn.at(i)), response, sizeof(response) - 1, &dwRead, NULL) != FALSE)
                {
                    response[dwRead] = '\0';
                    recieved = true;
                    break;
                }
            }
            else {
                printf("%d\n", GetLastError());
            }
        }
    }

Since I'm kind of new to C++ and using pipes, this doesn't make much sense to me. I was trying to replicate the method of communication exampled here. Any kind of advice will be considered useful.

Community
  • 1
  • 1
Zlatan Sičanica
  • 315
  • 2
  • 11

1 Answers1

2

You've shot yourself in the foot by unnecessarily complicating things.

        pipesIn.push_back(&hIn);

This is your problem. hIn is a stack-local variable that goes away at the end of the scope, but you're taking the address of that location on the stack and saving it.

The solution is for you to just make your vectors a std::vector<HANDLE>; HANDLEs are very small objects in the first place, the same size as a pointer, so you're not doing yourself any favors by taking them by address.

kfsone
  • 23,617
  • 2
  • 42
  • 74