thethiny
thethiny

Reputation: 1258

Wait for Named Pipe to be read before Disconnecting

I have a program written in Python that I need to contact from a C++ Program. I'm creating the Pipe Server on the C++ program with the client being in Python. I can't wrap my head around how to properly read/write between the 2 programs as each time I try a different behavior occurs. Note that I want the pipe to remain open for multiple reads/writes into the future.

Server (C++)

#include <windows.h>
#include <iostream>
using namespace std;

#define FGPIPE TEXT("\\\\.\\pipe\\FGChroma")

int main()
{

    HANDLE hPipe;
    DWORD dwWritten;
    DWORD MAX_BUF_SIZE = 8;

    hPipe = CreateNamedPipe(FGPIPE,
                            PIPE_ACCESS_OUTBOUND,
                            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                            2,
                            MAX_BUF_SIZE*16,
                            0,
                            NMPWAIT_USE_DEFAULT_WAIT,
                            NULL
                            );

    cout<<"Pipe? "<<hPipe<<endl;

    cout<<"Awaiting Connection"<<endl;
    cout<<ConnectNamedPipe(hPipe, NULL)<<endl;
    cout<<"Connected"<<endl;
    WriteFile(hPipe, "MSG1\n", 5, &dwWritten, NULL);
    WriteFile(hPipe, "MSG2\n", 5, &dwWritten, NULL);
    FlushFileBuffers(hPipe);
    ///Need to Wait for read here
    cout<<"Disconnecting"<<endl;
    DisconnectNamedPipe(hPipe);

}

Client (Python)

f = open(r"\\.\\pipe\\FGChroma", 'r', 0)
while True:
    value = f.read()
    print(value)

When I attempt to do the f.read() in Python, I get an error OSError 22 Invalid Argument, which is fair since I've disconnected the pipe. However if I don't disconnect the pipe then the Python code never finishes reading and keeps waiting until the pipe is closed or disconnected. I feel like the solution is simple and I'm just missing something tiny that's going over my head. I read the Documentation for named pipes and the Win APIs, I also tried win32py and other alternatives and I face the same issue; I don't understand how to keep a connection alive between the 2 instances and allow for reading without having to disconnect, or to wait for reading.

Upvotes: 0

Views: 905

Answers (3)

thethiny
thethiny

Reputation: 1258

Based on ElderBug's answer above, here's a working solution that doesn't use buffers, but instead uses an end of line terminator. You may need to adjust your code accordingly.

def read_line(file_handle):
    EOF = False
    data = ""
    while True:
        try:
            c = file_handle.read(1).decode("utf-8")
        except OSError: # EOF
            EOF = True
            break
        if c == '\n':
            break
        if not c:
            EOF = True
            break
        data += c
    return data, EOF

print("Connecting to Pipe")
while True:
    try:
        f = open(r"\\.\\pipe\\FGChroma", 'rb', 0)
        break
    except FileNotFoundError:
        continue

print("Connected")

print("Reading Data")

while True:
    data, EOF = read_line(f)
    if EOF: break
    print(data)

You may need to switch read mode from 'rb' to 'r' as well. Use b only for Binary mode, but then you'll have to enable buffering by setting buffer mode to 1 from 0.

Upvotes: 0

ElderBug
ElderBug

Reputation: 6145

I think there is a problem with Python f.read() and Windows pipes. Maybe I missed something but it looks like there is no EOF when you read a pipe like you do, and python read() will read past the end and error, even though it read everything correctly before.

To work around this, you can use a buffered pipe (open(r"pipe", 'r')) and then either read characters one by one (f.read(1)) until you have an error, or use os.read(f.fileno(), 1024), which is lower level and works in this case.

Upvotes: 1

user3732793
user3732793

Reputation: 1959

you can have a look here Python and Windows Named Pipes

thought on windows open a file by more than one program is not like on unix. If you can't avoid it use win32pipe but that makes your code not plattform indipendent

Upvotes: 0

Related Questions