9

I'm learning about named pipes and was playing with the named pipe client and server examples from the MSDN doc:

Named Pipe Server

Named Pipe Client

I modified the client so I can type in messages to the console and have them sent to the server where it displays the message and sends back a reply. Essentially I added a loop which starts after the SetNamedPipeHandleState() call and ends before the CloseHandle() call (i.e. the open and close happen outside the loop, so I am using the same pipe handle within the loop).

My question is, if I kill the client (by closing it or ending it via Task Manager) is there any way for the server side to detect the disconnect?

I've tried using GetNamedPipeHandleState() hoping it return failure and a call to GetLastError() would return ERROR_PIPE_NOT_CONNECTED, but that was not the case. Because of the way this server is set up I had to do this in the CompletedReadRoutine function and create a "controlled" failure. What I did was, with a breakpoint on the CompletedReadRoutine in the server:

  1. started the server
  2. started the client
  3. sent a message via the client (hits the breakpoint in the server here)
  4. killed the client
  5. Stepped through to the GetNamedPipeHandleState

The call to GetNamedPipeHandleState() returns successfully so I never got to do the GetLastError() call. When it gets to the WriteFileEx call it fails and a call to GetLastError at that point returns an ERROR_NO_DATA.

Looking at the pipe functions I can't see anything else that would possibly help here. I am missing something or is a client disconnect just not detectable.

The only other thing I can think of is collecting the pid's of the connecting clients (via GetNamedPipeClientProcessId) and spinning off watchdog threads to check if they are still alive. Though, just thinking about doing that sets off my spidey sense.

Is there a way to detect disconnected clients when using named pipes?

Robert Groves
  • 7,114
  • 5
  • 34
  • 49

2 Answers2

6

Doesn't ReadFile() return and error and GetLastError() then return ERROR_BROKEN_PIPE?

Len Holgate
  • 20,256
  • 4
  • 40
  • 89
  • Only if I kill the client very carefully using breakpoints in the server so I can kill the client at a specific piont in the server logic. For example, if I start the client and kill it right after initial connection but before the first time the server calls ReadFileEx, then yes I get ERROR_BROKEN_PIPE. The problem is the server waits on the call to WaitForSingleObjectEx. If the client side goes down it doesn't write to or read from that previosly connected to pipe instance. – Robert Groves Mar 04 '10 at 19:48
  • 3
    I don't really think those samples are that good an example of how to do things... Personally I'd always have an overlapped read pending on the pipe, that way you should always get a notification when the client goes away... – Len Holgate Mar 04 '10 at 21:21
  • I hear you and agree that the examples I have are not what I should be looking at for the way I'd like the commmunication to work. Thanks for your input. – Robert Groves Mar 05 '10 at 05:52
  • 2
    I have a similar issue where the named pipe server uses overlapped I/O and a thread is waiting on the Event objects of the OVERLAPPED structure. The issue is that when a client disconnects there is no event signaled on the server side of the pipe even though a ReadFile (overlapped I/O) has been called on the server side. EDIT: I tried to post this as a comment on the previous answer but was unable to. –  Aug 09 '10 at 13:11
1

ReadFile() + GetLastError() do the job well. Here is how they can be used with I/O Completion Ports (my implementation is in python+ctypes, but the idea should be clear):

def connect():
    GetQueuedCompletionStatus()
    receive()

def receive():
    while True:
        ret_code = ReadFile()
        if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE:
            # client disconnected
        GetQueuedCompletionStatus()

We are waiting for a completion packet, and when a client connects, we switch to the main loop. In the main loop we read the pipe and check if the client has disconnected by looking at ReadFile() return code and GetLastError(). Then again, we will wait for a completion packet.

A client can disconnect on any stage. Completion packet will be queued and we will get ERROR_BROKEN_PIPE.

wombatonfire
  • 2,718
  • 19
  • 33
  • Which programming language is this? It looks a bit like Python, but AFAIK `winapi` is C, C++, C# and Visual Basic only. – wizzwizz4 Oct 15 '16 at 10:29
  • Yes, this is Python, but you can call winapi functions using ctypes library. A mechanism that allows this is called FFI: https://en.wikipedia.org/wiki/Foreign_function_interface – wombatonfire Oct 15 '16 at 10:40