Redirecting stderr: in single process, *not* in a child process.
Hello all.
I spent a long day yesterday battling trying to achieve something that
sounds very simple until you actually try and do it. Let me explain
the situation:
I've taken a third party bit of server software that comes with a BSD
license and I have written a thin wrapper for it using our standard C+
+ classes for logging, configuration, service management etc. The
source code for the original software is basically unchanged, and I
want to keep it this way so that is simple to upgrade it when need be.
The problem is that the software uses simple c-style logging to
stderr, using fprintf mostly. What I want to do is capture this
output and send it somewhere else within my own application.
On unix I have solved this problem in the following manner:
• Create a pair of interconnected sockets using the "socketpair" call.
• Use dup2 to make stderr send its output to one of these sockets.
• Start a thread to monitor the other end of the socket and process
the output as it arrives.
This would all work fine on windows except on win32, sockets are not
the same as file descriptors. In short the method I am using on Unix
will not work on windows, or not that I can see.
I've spent hours trying to find an alternative solution to this simple
problem, playing with SetStdHandler, pipes, named pipes, sockets and
all sorts. I have yet to find a way to redirect everything sent to
"stderr" to a place of my choosing.
An example of how hard this is can be seen in the following code:
<code>
///
/// Function: main()
///
int main ( int argc, char * const argv[] )
{
HANDLE hRead, hWrite;
if ( !CreatePipe( &hRead, &hWrite ,NULL, 10 ) )
return FALSE;
SetStdHandle( STD_ERROR_HANDLE, hWrite );
fprintf( stderr, "This will NOT go to the pipe, but instead to the
console\n" );
return 0;
}
</code>
Even though I redirect the stderr to my pipe, that output will go to
the screen. Apparantly stderr has already been setup within the
printf code, and calling SetStdHandle has no effect.
In short I'm completely stumped. If someone can show me a way to do
this I would be most grateful. All examples on the web seem to be
oriented towards how to redirect the output of a child process, which
is really not what I'm trying to do here.
Thanks in advance.
Jamie
Re: Redirecting stderr: in single process, *not* in a child process.
JKP wrote:[color=blue]
> Hello all.
>
> I spent a long day yesterday battling trying to achieve something that
> sounds very simple until you actually try and do it. Let me explain
> the situation:
>
> I've taken a third party bit of server software that comes with a BSD
> license and I have written a thin wrapper for it using our standard C+
> + classes for logging, configuration, service management etc. The
> source code for the original software is basically unchanged, and I
> want to keep it this way so that is simple to upgrade it when need be.
>
> The problem is that the software uses simple c-style logging to
> stderr, using fprintf mostly. What I want to do is capture this
> output and send it somewhere else within my own application.
>
> On unix I have solved this problem in the following manner:
>
> • Create a pair of interconnected sockets using the "socketpair" call.
> • Use dup2 to make stderr send its output to one of these sockets.
> • Start a thread to monitor the other end of the socket and process
> the output as it arrives.
>
> This would all work fine on windows except on win32, sockets are not
> the same as file descriptors. In short the method I am using on Unix
> will not work on windows, or not that I can see.
>
> I've spent hours trying to find an alternative solution to this simple
> problem, playing with SetStdHandler, pipes, named pipes, sockets and
> all sorts. I have yet to find a way to redirect everything sent to
> "stderr" to a place of my choosing.
>
> An example of how hard this is can be seen in the following code:
>
> <code>
> ///
> /// Function: main()
> ///
> int main ( int argc, char * const argv[] )
> {
> HANDLE hRead, hWrite;
>
> if ( !CreatePipe( &hRead, &hWrite ,NULL, 10 ) )
> return FALSE;
>
> SetStdHandle( STD_ERROR_HANDLE, hWrite );
>
> fprintf( stderr, "This will NOT go to the pipe, but instead to the
> console\n" );
>
> return 0;
> }
> </code>
>
> Even though I redirect the stderr to my pipe, that output will go to
> the screen. Apparantly stderr has already been setup within the
> printf code, and calling SetStdHandle has no effect.
>
> In short I'm completely stumped. If someone can show me a way to do
> this I would be most grateful. All examples on the web seem to be
> oriented towards how to redirect the output of a child process, which
> is really not what I'm trying to do here.
>
> Thanks in advance.
>
> Jamie[/color]
Try using _pipe() and _dup2().
--
Norm
To reply, change domain to an adult feline.
Re: Redirecting stderr: in single process, *not* in a child process.
try it.
FILE *p = freopen("c:\\a.txt", "w", stderr);
fprintf(stderr, "Anand");
fclose(p);
Thanks
Anand
On Aug 15, 6:29*pm, Norman Bullen <n...@BlackKittenAssociates.com>
wrote:[color=blue]
> JKP wrote:[color=green]
> > Hello all.[/color]
>[color=green]
> > I spent a long day yesterday battling trying to achieve something that
> > sounds very simple until you actually try and do it. *Let me explain
> > the situation:[/color]
>[color=green]
> > I've taken a third party bit of server software that comes with a BSD
> > license and I have written a thin wrapper for it using our standard C+
> > + classes for logging, configuration, service management etc. *The
> > source code for the original software is basically unchanged, and I
> > want to keep it this way so that is simple to upgrade it when need be.[/color]
>[color=green]
> > The problem is that the software uses simple c-style logging to
> > stderr, using fprintf mostly. *What I want to do is capture this
> > output and send it somewhere else within my own application.[/color]
>[color=green]
> > On unix I have solved this problem in the following manner:[/color]
>[color=green]
> > • Create a pair of interconnected sockets using the "socketpair" call..
> > • Use dup2 to make stderr send its output to one of these sockets.
> > • Start a thread to monitor the other end of the socket and process
> > the output as it arrives.[/color]
>[color=green]
> > This would all work fine on windows except on win32, sockets are not
> > the same as file descriptors. *In short the method I am using on Unix
> > will not work on windows, or not that I can see.[/color]
>[color=green]
> > I've spent hours trying to find an alternative solution to this simple
> > problem, playing with SetStdHandler, pipes, named pipes, sockets and
> > all sorts. *I have yet to find a way to redirect everything sent to
> > "stderr" to a place of my choosing.[/color]
>[color=green]
> > An example of how hard this is can be seen in the following code:[/color]
>[color=green]
> > <code>
> > ///
> > /// Function: main()
> > ///
> > int main ( int argc, char * const argv[] )
> > {
> > * *HANDLE hRead, hWrite;[/color]
>[color=green]
> > * *if ( !CreatePipe( &hRead, &hWrite ,NULL, 10 ) )
> > * * * * * *return FALSE;[/color]
>[color=green]
> > * *SetStdHandle( STD_ERROR_HANDLE, hWrite );[/color]
>[color=green]
> > * *fprintf( stderr, "This will NOT go to the pipe, but instead to the
> > console\n" );[/color]
>[color=green]
> > * *return 0;
> > }
> > </code>[/color]
>[color=green]
> > Even though I redirect the stderr to my pipe, that output will go to
> > the screen. *Apparantly stderr has already been setup within the
> > printf code, and calling SetStdHandle has no effect.[/color]
>[color=green]
> > In short I'm completely stumped. *If someone can show me a way to do
> > this I would be most grateful. *All examples on the web seem to be
> > oriented towards how to redirect the output of a child process, which
> > is really not what I'm trying to do here.[/color]
>[color=green]
> > Thanks in advance.[/color]
>[color=green]
> > Jamie[/color]
>
> Try using _pipe() and _dup2().
>
> --
> Norm
>
> To reply, change domain to an adult feline.[/color]
Re: Redirecting stderr: in single process, *not* in a child process.
Hi Jamie, I've had a similar problem in Windows -- redirecting stderr to a named pipe NOT in a child process -- and solved it thus:
1. Create a named pipe using [I]CreateFile()[/I] if the code is to to be a pipe client, or [I]CreateNamedPipe() [/I]+[I] ConnectNamedPipe() [/I]if it's to be a pipe server. You might need to spawn a thread to listen for connections depending on how your program works.
2. I don't like working in the Windows() world with file and stream I/O, so I take the Windows file handle for the pipe and make a C file descriptor of it, using [I]_open_osfhandle()[/I]. I then call [I]_fdopen() [/I]on the file descriptor, so I now have a FILE * representing my output pipe handle. Let's call the FILE * [B]fout[/B].
3. [font=courier new]*stderr = *fout; // now, all code writing to stderr goes to fout[/font]
4. [font=courier new]setvbuf(stderr, NULL, _IONBF, 0); // Things dont work unless we make stderr unbuffered[/font]
That's it. Let me know if you want details/code.
Re: Redirecting stderr: in single process, *not* in a child process.
>> That's it. Let me know if you want details/code.
Hi
Please, if still possible, could you post further details?? Win32 API will always be a mistery for me...
Thx!