views:

222

answers:

5
  hPipe = CreateNamedPipe( 
     lpszPipename,             // pipe name 
     PIPE_ACCESS_DUPLEX,       // read/write access 
     PIPE_TYPE_MESSAGE |       // message type pipe 
     PIPE_READMODE_MESSAGE |   // message-read mode 
     PIPE_WAIT,                // blocking mode 
     PIPE_UNLIMITED_INSTANCES, // max. instances  
     100,                  // output buffer size 
     100,                  // input buffer size 
     0,                        // client time-out 
     NULL);                    // default security attribute 

  DWORD totalBytesAvailable; 
  PeekNamedPipe( 
    hPipe ,                // __in       HANDLE hNamedPipe, 
    NULL,                  // __out_opt  LPVOID lpBuffer, 
    0,                     // __in       DWORD nBufferSize, 
    NULL,                  // __out_opt  LPDWORD lpBytesRead, 
    &totalBytesAvailable,  // __out_opt  LPDWORD lpTotalBytesAvail, 
    NULL                   // __out_opt  LPDWORD lpBytesLeftThisMessage 
  ); 
    if(totalBytesAvailable allows)
    WriteFile( tmp_pipe, pBuffer, BufferLen, &dwWritten, NULL );

As you see I used PeekNamedPipe to get available space,but it turns out that totalBytesAvailable is always 0,how to do it properly?

+1  A: 

You can't determine the free space in the way you are doing it.

While this question is about pipes, it's possible people may come across it looking for general information on discovering available disk space, and if the pipe is ultimately a file, this might still be useful:

The Knowledge Base article "Understanding and Using GetDiskFreeSpace and GetDiskFreeSpaceEx" gives info on the relevant Win32 APIs for determine free disk space, or go straight to the API documentation here:

Paul Dixon
-1, pipe != disk.
MSalters
I realise that, will edit to clarify. The way the question is phrased is likely to lead people who are searching for a way to find free disk space though, so I thought it would still be useful.
Paul Dixon
+3  A: 

IMHO, this approach of checking the free space before doing the actual write is flawed.

It might happen that by the time the actual write gets executed, some other process running in parallel fills out the last bits of free disk space thus causing your WriteFile to fail.

I would rely only on what WriteFile returns.

tudor
I can't rely on `WriteFile`,it'll hang! And there's no need to worry about the multi-thread case in my case.
Alan
No this is the correct way to do it. Other processes share the disk, you can't guarantee that they won't fill empty space you presumed to claim either. The call won't hang if an error occurs (such as no disk space). You should get something like `GetLastError() == ERROR_DISK_FULL` after the call.
Matt Joiner
The call will hang if there's no space left for `WriteFile`,which I'm to avoid.
wamp
+1  A: 

Hi ALan,

The values returned in the lpTotalBytesAvail parameter is the number of bytes that may be read from a pipe, not written to the pipe. Give you the information to allocate a buffer reading data from a pipe.

The correct approach to handling errors when writing to a pipe - or any NT Krenel handle -- is to simply execute the call to WriteFile() and handle any errors returned.

The check then write pattern is not effective and will yield bugs that * Never happen in your tests * Happen sometimes in the field * ... and are thus very difficult to diagnose and debug * most importantly, such bugs will annoy your users.

The reason is that the state of the destination can change between the check and the actual write. This means that your code that calls WriteFile() must check for errors anyway. This means that checking for a pre-condition before calling WriteFile()is simply extra code that provides no value.

The reason this pattern isn't effective is that Windows (and all other operating systems - this isn't just a windows thing) - cannot treat the "check" and the 'write" as atomic operations. The underlying OS is fully asynchronous and lots can happen between the calls.

So, your code will be simpler and more reliabile if you simple call WriteFile() and do a good job of error handling.

-Foredecker

Foredecker
There's no error,just hangs,which I'm to avoid.
wamp
+1  A: 

Set PIPE_NOWAIT instead of PIPE_WAIT. Then WriteFile will return immediately if there's not enough room in the pipe.
And 100 seems rather small for the I/O buffer sizes! What is your pipe for?

TonyK
PIPE_NOWAIT will always return immediately...
pascal
That's what I said, isn't it?
TonyK
Then you won't know whether `WriteFile` succeeds or not.
Alan
If WriteFile doesn't succeed, it returns with an error code, instead of hanging. Which is what the OP wanted. (There seems to be no actual file involved here, if I understand the question.)
TonyK
A: 

Create a thread to handle to writing to the pipe, so that it's not a problem having the writer hang, waiting for the client to empty the pipe?

pascal