You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "William A. Rowe, Jr." <wr...@rowe-clan.net> on 2001/02/24 22:05:09 UTC

Diagnosing W2K service bugreports

I've noticed something very interesting in the Win32 code.

Services gain no stdin/out/err handles as the parent is launched.
I suspected this could be confusing perl56.dll when it tries to
clean up before stopping the service.  That appears to _not_ be
the issue.  But there is a bug report, 7198 [hope I don't transpose
the digits yet again :-] that indicates the system fails on dup2(stdin)
when the user tries to use rotatelogs.  Now I've come up with the
following patch that introduces "NUL" handles for win32 stdin/stdout,
and the stderr is already set to a pipe that captures all 'pre-logging'
fprintf(stderr...) stuff into the event log.

Here's the code I'm suggesting we include in 1.3.19 that resolves the
spawning rotatelogs bug after I test on NT (it's already tested on Win2K):

Index: service.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v
retrieving revision 1.44
diff -u -r1.44 service.c
--- service.c 2001/02/21 00:36:38 1.44
+++ service.c 2001/02/24 21:00:13
@@ -547,6 +547,7 @@
     HANDLE hCurrentProcess;
     HANDLE hPipeRead = NULL;
     HANDLE hPipeReadDup;
+    HANDLE hNullFile;
     DWORD  threadid;
     SECURITY_ATTRIBUTES sa = {0};
     char **newargv;
@@ -601,6 +602,46 @@
             CloseHandle(eventlog_pipewrite);
             eventlog_pipewrite = NULL;
         }            
+    }
+
+    /* Open a null handle to spoof our stdin */
+    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, 
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                           &sa, OPEN_EXISTING, 0, NULL);
+    if (hNullFile == INVALID_HANDLE_VALUE) {
+        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+                     "Parent: Unable to create null stdin pipe for this service process.\n");
+    }
+    else {
+        int fh;
+        FILE *fl;
+        fflush(stdin);
+        SetStdHandle(STD_INPUT_HANDLE, hNullFile);
+        fh = _open_osfhandle((long) STD_INPUT_HANDLE, 
+                             _O_WRONLY | _O_BINARY);
+        dup2(fh, STDIN_FILENO);
+        fl = _fdopen(STDIN_FILENO, "wcb");
+        memcpy(stdin, fl, sizeof(FILE));
+    }
+
+    /* Open a null handle to soak our stdout */
+    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, 
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                           &sa, OPEN_EXISTING, 0, NULL);
+    if (hNullFile == INVALID_HANDLE_VALUE) {
+        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+                     "Parent: Unable to create null stdout pipe for this service process.\n");
+    }
+    else {
+        int fh;
+        FILE *fl;
+        fflush(stdout);
+        SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
+        fh = _open_osfhandle((long) STD_OUTPUT_HANDLE, 
+                             _O_WRONLY | _O_BINARY);
+        dup2(fh, STDOUT_FILENO);
+        fl = _fdopen(STDOUT_FILENO, "wcb");
+        memcpy(stdout, fl, sizeof(FILE));
     }
 
     atexit(service_main_fn_terminate);




Re: [PATCH 1.3] Diagnosing W2K service bugreports

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
From: "Bill Stoddard" <bi...@wstoddard.com>
Sent: Monday, February 26, 2001 12:15 PM


> Not tested, but I am +1 for taking the chance and including it in the build.
> Hav eyou tested to make sure CGIs work still? If it breaks anything, I would
> expect it be 95/98.

Sorry... just recovering from a crashed mbox monday.  This is in the NT/W2K only
code path, won't affect 95/98.  Already committed.


Re: [PATCH 1.3] Diagnosing W2K service bugreports

Posted by Bill Stoddard <bi...@wstoddard.com>.
Not tested, but I am +1 for taking the chance and including it in the build.
Hav eyou tested to make sure CGIs work still? If it breaks anything, I would
expect it be 95/98.

Bill


----- Original Message -----
From: William A. Rowe, Jr. <wr...@rowe-clan.net>
To: <ne...@apache.org>; <v....@gte.net>; Bill Stoddard
<bi...@wstoddard.com>
Sent: Monday, February 26, 2001 11:27 AM
Subject: [PATCH 1.3] Diagnosing W2K service bugreports


> This bugfix should go in if we want rotatelogs to behave correctly, per
PR7198
> and Victor's observations.  I don't know, Martin, if you can let this one
> slide in, and unless FirstBill and Victor can both comment in the next few
> minutes, I'm expecting we will loose any window for the patch.
>
> We were -1 (?) from FirstBill, who posted that we should fix the behavior
that
> broke the code.  Unfortunately, it was MS + our introduction of piped logs
into
> Win32, which never worked before my patch to 1.3.13-dev.  Bill, please
clarify.
>
> I can find no fault with the code, yet I've been playing some very odd games
> trying to break the server with this patch (amongst others that I don't
propose
> today.)
>
> The concept of the patch is this: Win32 services aren't getting valid
handles
> for their stdin/stdout/stderr.  We have fixed stderr to dump into the event
> log through a seperate thread and pipe.  This simply introduces handles to
the
> "NUL" device on Win32 for stdin/stdout.
>
> Comments?
>
> Bill
>
> ----- Original Message -----
> From: "William A. Rowe, Jr." <wr...@rowe-clan.net>
> To: <ne...@apache.org>
> Sent: Saturday, February 24, 2001 3:05 PM
> Subject: Diagnosing W2K service bugreports
>
>
> > I've noticed something very interesting in the Win32 code.
> >
> > Services gain no stdin/out/err handles as the parent is launched.
> > I suspected this could be confusing perl56.dll when it tries to
> > clean up before stopping the service.  That appears to _not_ be
> > the issue.  But there is a bug report, 7198 [hope I don't transpose
> > the digits yet again :-] that indicates the system fails on dup2(stdin)
> > when the user tries to use rotatelogs.  Now I've come up with the
> > following patch that introduces "NUL" handles for win32 stdin/stdout,
> > and the stderr is already set to a pipe that captures all 'pre-logging'
> > fprintf(stderr...) stuff into the event log.
> >
> > Here's the code I'm suggesting we include in 1.3.19 that resolves the
> > spawning rotatelogs bug after I test on NT (it's already tested on Win2K):
>
>  Index: service.c
> ===================================================================
> RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v
> retrieving revision 1.44
> diff -u -r1.44 service.c
> --- service.c 2001/02/21 00:36:38 1.44
> +++ service.c 2001/02/24 21:00:13
> @@ -547,6 +547,7 @@
>      HANDLE hCurrentProcess;
>      HANDLE hPipeRead = NULL;
>      HANDLE hPipeReadDup;
> +    HANDLE hNullFile;
>      DWORD  threadid;
>      SECURITY_ATTRIBUTES sa = {0};
>      char **newargv;
> @@ -601,6 +602,46 @@
>              CloseHandle(eventlog_pipewrite);
>              eventlog_pipewrite = NULL;
>          }
> +    }
> +
> +    /* Open a null handle to spoof our stdin */
> +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                           &sa, OPEN_EXISTING, 0, NULL);
> +    if (hNullFile == INVALID_HANDLE_VALUE) {
> +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> +                     "Parent: Unable to create null stdin pipe for this
service process.\n");
> +    }
> +    else {
> +        int fh;
> +        FILE *fl;
> +        fflush(stdin);
> +        SetStdHandle(STD_INPUT_HANDLE, hNullFile);
> +        fh = _open_osfhandle((long) STD_INPUT_HANDLE,
> +                             _O_RDONLY | _O_BINARY);
> +        dup2(fh, STDIN_FILENO);
> +        fl = _fdopen(STDIN_FILENO, "rcb");
> +        memcpy(stdin, fl, sizeof(FILE));
> +    }
> +
> +    /* Open a null handle to soak our stdout */
> +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                           &sa, OPEN_EXISTING, 0, NULL);
> +    if (hNullFile == INVALID_HANDLE_VALUE) {
> +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> +                     "Parent: Unable to create null stdout pipe for this
service process.\n");
> +    }
> +    else {
> +        int fh;
> +        FILE *fl;
> +        fflush(stdout);
> +        SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
> +        fh = _open_osfhandle((long) STD_OUTPUT_HANDLE,
> +                             _O_WRONLY | _O_BINARY);
> +        dup2(fh, STDOUT_FILENO);
> +        fl = _fdopen(STDOUT_FILENO, "wcb");
> +        memcpy(stdout, fl, sizeof(FILE));
>      }
>
>      atexit(service_main_fn_terminate);
>
>
>


Re: [PATCH 1.3] Diagnosing W2K service bugreports

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Mon, Feb 26, 2001 at 11:04:24AM -0600, William A. Rowe, Jr. wrote:
> 
> Martin, your opinion?

I'm sorry, but some of the mails on this list looped for 2h30m on
an exchange server somewhere in my company. I didn't get to read this
until the tar ball was rolled. Also, I'm a little hesitant to accept
patches to a platform which I cannot test, and only a couple of
minutes before building a tar ball. A couple of other patches have
been held back, and I think it's best if we add this to 1.3.20-dev
and test it sufficiently (on Win9x++) before releasing that.

Sorry, but please understand that as a RM I must be very reluctant
to accept last minute changes (and in this case I even couldn't).

  Martin
-- 
<Ma...@Fujitsu-Siemens.com>    |       Fujitsu Siemens
       <ma...@apache.org>              |   81730  Munich,  Germany

Re: [PATCH 1.3] Diagnosing W2K service bugreports

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
From: "Victor J. Orlikowski" <v....@gte.net>
Sent: Monday, February 26, 2001 10:38 AM


> +1 for me.

Then I would like to see this go in.

Martin, your opinion?


Re: [PATCH 1.3] Diagnosing W2K service bugreports

Posted by "Victor J. Orlikowski" <v....@gte.net>.
+1 for me.
-- 
Victor J. Orlikowski
======================
v.j.orlikowski@gte.net
orlikowski@apache.org
vjo@us.ibm.com


[PATCH 1.3] Diagnosing W2K service bugreports

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
This bugfix should go in if we want rotatelogs to behave correctly, per PR7198 
and Victor's observations.  I don't know, Martin, if you can let this one
slide in, and unless FirstBill and Victor can both comment in the next few
minutes, I'm expecting we will loose any window for the patch.

We were -1 (?) from FirstBill, who posted that we should fix the behavior that
broke the code.  Unfortunately, it was MS + our introduction of piped logs into
Win32, which never worked before my patch to 1.3.13-dev.  Bill, please clarify.

I can find no fault with the code, yet I've been playing some very odd games
trying to break the server with this patch (amongst others that I don't propose
today.)

The concept of the patch is this: Win32 services aren't getting valid handles
for their stdin/stdout/stderr.  We have fixed stderr to dump into the event
log through a seperate thread and pipe.  This simply introduces handles to the
"NUL" device on Win32 for stdin/stdout.

Comments?

Bill

----- Original Message ----- 
From: "William A. Rowe, Jr." <wr...@rowe-clan.net>
To: <ne...@apache.org>
Sent: Saturday, February 24, 2001 3:05 PM
Subject: Diagnosing W2K service bugreports


> I've noticed something very interesting in the Win32 code.
> 
> Services gain no stdin/out/err handles as the parent is launched.
> I suspected this could be confusing perl56.dll when it tries to
> clean up before stopping the service.  That appears to _not_ be
> the issue.  But there is a bug report, 7198 [hope I don't transpose
> the digits yet again :-] that indicates the system fails on dup2(stdin)
> when the user tries to use rotatelogs.  Now I've come up with the
> following patch that introduces "NUL" handles for win32 stdin/stdout,
> and the stderr is already set to a pipe that captures all 'pre-logging'
> fprintf(stderr...) stuff into the event log.
> 
> Here's the code I'm suggesting we include in 1.3.19 that resolves the
> spawning rotatelogs bug after I test on NT (it's already tested on Win2K):
 
 Index: service.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v
retrieving revision 1.44
diff -u -r1.44 service.c
--- service.c 2001/02/21 00:36:38 1.44
+++ service.c 2001/02/24 21:00:13
@@ -547,6 +547,7 @@
     HANDLE hCurrentProcess;
     HANDLE hPipeRead = NULL;
     HANDLE hPipeReadDup;
+    HANDLE hNullFile;
     DWORD  threadid;
     SECURITY_ATTRIBUTES sa = {0};
     char **newargv;
@@ -601,6 +602,46 @@
             CloseHandle(eventlog_pipewrite);
             eventlog_pipewrite = NULL;
         }            
+    }
+
+    /* Open a null handle to spoof our stdin */
+    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, 
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                           &sa, OPEN_EXISTING, 0, NULL);
+    if (hNullFile == INVALID_HANDLE_VALUE) {
+        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+                     "Parent: Unable to create null stdin pipe for this service process.\n");
+    }
+    else {
+        int fh;
+        FILE *fl;
+        fflush(stdin);
+        SetStdHandle(STD_INPUT_HANDLE, hNullFile);
+        fh = _open_osfhandle((long) STD_INPUT_HANDLE, 
+                             _O_RDONLY | _O_BINARY);
+        dup2(fh, STDIN_FILENO);
+        fl = _fdopen(STDIN_FILENO, "rcb");
+        memcpy(stdin, fl, sizeof(FILE));
+    }
+
+    /* Open a null handle to soak our stdout */
+    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, 
+                           FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                           &sa, OPEN_EXISTING, 0, NULL);
+    if (hNullFile == INVALID_HANDLE_VALUE) {
+        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
+                     "Parent: Unable to create null stdout pipe for this service process.\n");
+    }
+    else {
+        int fh;
+        FILE *fl;
+        fflush(stdout);
+        SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
+        fh = _open_osfhandle((long) STD_OUTPUT_HANDLE, 
+                             _O_WRONLY | _O_BINARY);
+        dup2(fh, STDOUT_FILENO);
+        fl = _fdopen(STDOUT_FILENO, "wcb");
+        memcpy(stdout, fl, sizeof(FILE));
     }
 
     atexit(service_main_fn_terminate);




Re: Diagnosing W2K service bugreports

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
Nak... This is Windows 2000 bogosity.  First off, older versions of Apache _never_ supported
piped log files - that was my patch (1.3.12?  1.3.14?  I forget.)  Second, this patch may be
unneeded on WinNT - have already warned that this isn't tested (for success or applicability)
on the Windows NT 4.0 box, just yet.

Bill

----- Original Message ----- 
From: "Bill Stoddard" <bi...@wstoddard.com>
To: <ne...@apache.org>
Sent: Saturday, February 24, 2001 4:05 PM
Subject: Re: Diagnosing W2K service bugreports


> This is a new problem introduced by some earlier change. I suggest we identify what broke this
> rather than add more cycle consuming cruft.
> 
> Bill
> 
> ----- Original Message -----
> From: "William A. Rowe, Jr." <wr...@rowe-clan.net>
> To: <ne...@apache.org>
> Sent: Saturday, February 24, 2001 4:05 PM
> Subject: Diagnosing W2K service bugreports
> 
> 
> > I've noticed something very interesting in the Win32 code.
> >
> > Services gain no stdin/out/err handles as the parent is launched.
> > I suspected this could be confusing perl56.dll when it tries to
> > clean up before stopping the service.  That appears to _not_ be
> > the issue.  But there is a bug report, 7198 [hope I don't transpose
> > the digits yet again :-] that indicates the system fails on dup2(stdin)
> > when the user tries to use rotatelogs.  Now I've come up with the
> > following patch that introduces "NUL" handles for win32 stdin/stdout,
> > and the stderr is already set to a pipe that captures all 'pre-logging'
> > fprintf(stderr...) stuff into the event log.
> >
> > Here's the code I'm suggesting we include in 1.3.19 that resolves the
> > spawning rotatelogs bug after I test on NT (it's already tested on Win2K):
> >
> > Index: service.c
> > ===================================================================
> > RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v
> > retrieving revision 1.44
> > diff -u -r1.44 service.c
> > --- service.c 2001/02/21 00:36:38 1.44
> > +++ service.c 2001/02/24 21:00:13
> > @@ -547,6 +547,7 @@
> >      HANDLE hCurrentProcess;
> >      HANDLE hPipeRead = NULL;
> >      HANDLE hPipeReadDup;
> > +    HANDLE hNullFile;
> >      DWORD  threadid;
> >      SECURITY_ATTRIBUTES sa = {0};
> >      char **newargv;
> > @@ -601,6 +602,46 @@
> >              CloseHandle(eventlog_pipewrite);
> >              eventlog_pipewrite = NULL;
> >          }
> > +    }
> > +
> > +    /* Open a null handle to spoof our stdin */
> > +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> > +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> > +                           &sa, OPEN_EXISTING, 0, NULL);
> > +    if (hNullFile == INVALID_HANDLE_VALUE) {
> > +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> > +                     "Parent: Unable to create null stdin pipe for this service process.\n");
> > +    }
> > +    else {
> > +        int fh;
> > +        FILE *fl;
> > +        fflush(stdin);
> > +        SetStdHandle(STD_INPUT_HANDLE, hNullFile);
> > +        fh = _open_osfhandle((long) STD_INPUT_HANDLE,
> > +                             _O_WRONLY | _O_BINARY);
> > +        dup2(fh, STDIN_FILENO);
> > +        fl = _fdopen(STDIN_FILENO, "wcb");
> > +        memcpy(stdin, fl, sizeof(FILE));
> > +    }
> > +
> > +    /* Open a null handle to soak our stdout */
> > +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> > +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> > +                           &sa, OPEN_EXISTING, 0, NULL);
> > +    if (hNullFile == INVALID_HANDLE_VALUE) {
> > +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> > +                     "Parent: Unable to create null stdout pipe for this service process.\n");
> > +    }
> > +    else {
> > +        int fh;
> > +        FILE *fl;
> > +        fflush(stdout);
> > +        SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
> > +        fh = _open_osfhandle((long) STD_OUTPUT_HANDLE,
> > +                             _O_WRONLY | _O_BINARY);
> > +        dup2(fh, STDOUT_FILENO);
> > +        fl = _fdopen(STDOUT_FILENO, "wcb");
> > +        memcpy(stdout, fl, sizeof(FILE));
> >      }
> >
> >      atexit(service_main_fn_terminate);
> >
> >
> >
> 
> 


Re: Diagnosing W2K service bugreports

Posted by Bill Stoddard <bi...@wstoddard.com>.
This is a new problem introduced by some earlier change. I suggest we identify what broke this
rather than add more cycle consuming cruft.

Bill

----- Original Message -----
From: "William A. Rowe, Jr." <wr...@rowe-clan.net>
To: <ne...@apache.org>
Sent: Saturday, February 24, 2001 4:05 PM
Subject: Diagnosing W2K service bugreports


> I've noticed something very interesting in the Win32 code.
>
> Services gain no stdin/out/err handles as the parent is launched.
> I suspected this could be confusing perl56.dll when it tries to
> clean up before stopping the service.  That appears to _not_ be
> the issue.  But there is a bug report, 7198 [hope I don't transpose
> the digits yet again :-] that indicates the system fails on dup2(stdin)
> when the user tries to use rotatelogs.  Now I've come up with the
> following patch that introduces "NUL" handles for win32 stdin/stdout,
> and the stderr is already set to a pipe that captures all 'pre-logging'
> fprintf(stderr...) stuff into the event log.
>
> Here's the code I'm suggesting we include in 1.3.19 that resolves the
> spawning rotatelogs bug after I test on NT (it's already tested on Win2K):
>
> Index: service.c
> ===================================================================
> RCS file: /home/cvs/apache-1.3/src/os/win32/service.c,v
> retrieving revision 1.44
> diff -u -r1.44 service.c
> --- service.c 2001/02/21 00:36:38 1.44
> +++ service.c 2001/02/24 21:00:13
> @@ -547,6 +547,7 @@
>      HANDLE hCurrentProcess;
>      HANDLE hPipeRead = NULL;
>      HANDLE hPipeReadDup;
> +    HANDLE hNullFile;
>      DWORD  threadid;
>      SECURITY_ATTRIBUTES sa = {0};
>      char **newargv;
> @@ -601,6 +602,46 @@
>              CloseHandle(eventlog_pipewrite);
>              eventlog_pipewrite = NULL;
>          }
> +    }
> +
> +    /* Open a null handle to spoof our stdin */
> +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                           &sa, OPEN_EXISTING, 0, NULL);
> +    if (hNullFile == INVALID_HANDLE_VALUE) {
> +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> +                     "Parent: Unable to create null stdin pipe for this service process.\n");
> +    }
> +    else {
> +        int fh;
> +        FILE *fl;
> +        fflush(stdin);
> +        SetStdHandle(STD_INPUT_HANDLE, hNullFile);
> +        fh = _open_osfhandle((long) STD_INPUT_HANDLE,
> +                             _O_WRONLY | _O_BINARY);
> +        dup2(fh, STDIN_FILENO);
> +        fl = _fdopen(STDIN_FILENO, "wcb");
> +        memcpy(stdin, fl, sizeof(FILE));
> +    }
> +
> +    /* Open a null handle to soak our stdout */
> +    hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE,
> +                           FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                           &sa, OPEN_EXISTING, 0, NULL);
> +    if (hNullFile == INVALID_HANDLE_VALUE) {
> +        ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL,
> +                     "Parent: Unable to create null stdout pipe for this service process.\n");
> +    }
> +    else {
> +        int fh;
> +        FILE *fl;
> +        fflush(stdout);
> +        SetStdHandle(STD_OUTPUT_HANDLE, hNullFile);
> +        fh = _open_osfhandle((long) STD_OUTPUT_HANDLE,
> +                             _O_WRONLY | _O_BINARY);
> +        dup2(fh, STDOUT_FILENO);
> +        fl = _fdopen(STDOUT_FILENO, "wcb");
> +        memcpy(stdout, fl, sizeof(FILE));
>      }
>
>      atexit(service_main_fn_terminate);
>
>
>