Click here to Skip to main content
Click here to Skip to main content

Using Named Pipes for Tracing

By , 14 Jul 2004
 

Introduction

Traces are very useful tools for debugging purposes, especially if the program runs as a release version. It is easy to save the traces for a single application. But it needs a little work to receive the traces of multiple processes or even threads running at the same time in one single file or window. The example given here describes an elegant way to solve this problem. It uses "named pipes" for interprocess communication. Each process sends its trace data to one central special listener process. For the processes sending traces it doesn't matter if this listener process does or does not exist.

Background

A Named Pipe is a high level mechanism for the communication between processes even if they are running on different computers linked by a network. It hides all the communication details and offers two sides: One side to put data in and one side to read it out, but it can also be used bidirectional.

For building up a communication line, a process creates a pipe with a unique name. Using this name another process can connect to this pipe. Because a named pipe is a link between only two processes, it needs a set of named pipes to communicate with more then two processes at the same time. Each instance of these named pipe can use the same name.

The reading or writing of data to a pipe can be done with the normal set of Windows commands used to read or write data to a file. Like the normal file operations named pipes can be accessed in a blocking (= synchronous) or nonblocking (= asynchronous) mode. This example uses the synchronous communication mode because it is especially simple to use: The function calls to read or write data don't come back until the communication operation has finished. To allow communication with multiple processes it uses one thread for each pipe. Every time a new process connects to the listener, it creates a new pipe allowing the next process to connect with.

Using the code

For sending a trace, there is just a very easy interface needed: Building up the communication with Connect and sending traces with MakeTrace. The usage is demonstrated in the simple dialog based application TraceSender. You may start multiple instances of this program to generate more traffic.

class CTracer  
{
public:
  CTracer();
  virtual ~CTracer();

  bool Connect();
  bool MakeTrace(const char* pStr,...) const;    // use like printf(...)

private:
  HANDLE m_hPipe;

};

Because of its multithreading capability the mechanism for receiving traces is a little bit more complicate to implement. But its usage is as simple. This demonstrates the simple console application TraceListener:

#include "stdafx.h"
#include "conio.h"

#include "TraceCollector.h"

BOOL OnTrace(const char* pStr, DWORD nLength)
{
  _cputs(pStr);
  _cputs("\r\n");
  return TRUE;
}

int main(int argc, char* argv[])
{
  CTraceCollector tracer(OnTrace);
  tracer.Run();

  _getch();
  return 0;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Holger Kloos
United Kingdom United Kingdom
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalall pipe instance are busy GetLastError() = 231memberrahulagarwal3313 Oct '08 - 5:37 
i am running the trace listener and trace senders on different computers both are connected via lan.
 
when i "execute" trace listener and trace senders it works fine.
but when i run trace listener in debugger, GetLastError returns 231 when calling createfile in trace sender. any though about that?
GeneralExactly what I was looking for!membermi-chi23 Sep '07 - 19:44 
Great article!
 
I searched so many resources on named pipes in order to find a lightweight any simple solution for debug-logging.
 
Although writing a log file from code is possible, all write operations must be flushed immediately in order to be complete when the application crashes, which is a huge performance impact. That's exactly where named pipes come into play: buffered logging and surviving a crashing process.
 
Your client is very easy to implement and flexible enough for an application to log all important information.
 
Thank you so much!
GeneralPossible handle leakmemberJim Xochellis10 Oct '06 - 22:58 
Nice Job, very nice and clean coding! You have got my 5 Smile | :)
 
Nevertheless, I think there is a handle leak inside the CPipeListener::ReadPipe() method, since you never call CloseHandle(hPipe) for the hPipe handle. You can confirm the leak with the Task-Manager if you launch a few Trace-Senders and close them afterwards.
 
Moreover, a FlushFileBuffers(hPipe) call would be beneficial before closing the pipe handle, in order to to allow the clients to read the pipe's contents before disconnecting. (Please see the "Multithreaded Pipe Server" SDK example)
 
Best Regards,
Jim Xochellis

GeneralGlad you exist!memberphilFox15 Mar '06 - 17:09 
There was I, googling "named pipes for tracing", and here it is, already done. Saved me days in research, and all worked first time. Big thank you.
GeneralthanksmemberMoak1 Jul '05 - 0:41 
Your article came very handy for testing named pipes!
Cheers, Moak
GeneralTwo WordsmemberBrad Bruce15 Jul '04 - 6:47 
Awe Some OMG | :OMG:
 
Just what I needed. I'm trying to communicate from a service to an app that I have written and wanted to get away from sockets!!!!!
 
Good Work

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 15 Jul 2004
Article Copyright 2004 by Holger Kloos
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid