]> granicus.if.org Git - apache/commitdiff
Cleanup the eventlogger code, and split it into its own source.
authorWilliam A. Rowe Jr <wrowe@apache.org>
Thu, 14 Mar 2002 04:19:00 +0000 (04:19 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Thu, 14 Mar 2002 04:19:00 +0000 (04:19 +0000)
  [got the copyright correct, no less.]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93927 13f79535-47bb-0310-9956-ffa450edef68

server/mpm/winnt/mpm_winnt.h
server/mpm/winnt/nt_eventlog.c [new file with mode: 0644]

index 0e7fe35a345e6ff348315a0876896540e18db5cd..0a7b5262e0d654239bbb164bfab71ff5eb107540 100644 (file)
@@ -112,6 +112,11 @@ void mpm_service_stopping(void);
 void mpm_start_console_handler(void);
 void mpm_start_child_console_handler(void);
 
+/* From nt_eventlog.c: */
+
+void mpm_nt_eventlog_stderr_open(char *display_name, apr_pool_t *p);
+void mpm_nt_eventlog_stderr_flush(void);
+
 /* From winnt.c: */
 
 extern OSVERSIONINFO osver;
diff --git a/server/mpm/winnt/nt_eventlog.c b/server/mpm/winnt/nt_eventlog.c
new file mode 100644 (file)
index 0000000..962ebc7
--- /dev/null
@@ -0,0 +1,225 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
+#define CORE_PRIVATE 
+
+#include "httpd.h"
+#include "http_log.h"
+#include "mpm_winnt.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#include "apr_dbg_win32_handles.h"
+
+
+static char  *display_name  = NULL;
+static HANDLE stderr_thread = NULL;
+static HANDLE stderr_ready;
+
+static DWORD WINAPI service_stderr_thread(LPVOID hPipe)
+{
+    HANDLE hPipeRead = (HANDLE) hPipe;
+    HANDLE hEventSource;
+    char errbuf[256];
+    char *errmsg = errbuf;
+    const char *errarg[9];
+    DWORD errres;
+    HKEY hk;
+    
+    errarg[0] = "The Apache service named";
+    errarg[1] = display_name;
+    errarg[2] = "reported the following error:\r\n>>>";
+    errarg[3] = errbuf;
+    errarg[4] = NULL;
+    errarg[5] = NULL;
+    errarg[6] = NULL;
+    errarg[7] = NULL;
+    errarg[8] = NULL;
+
+    /* What are we going to do in here, bail on the user?  not. */
+    if (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services"
+                      "\\EventLog\\Application\\Apache Service", &hk)) 
+    {
+        /* The stock message file */
+        char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll";
+        DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
+                       EVENTLOG_INFORMATION_TYPE; 
+        RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,
+                          (LPBYTE) netmsgkey, strlen(netmsgkey) + 1);
+        
+        RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,
+                          (LPBYTE) &dwData, sizeof(dwData));
+        RegCloseKey(hk);
+    }
+
+    hEventSource = RegisterEventSource(NULL, "Apache Service");
+
+    SetEvent(stderr_ready);
+
+    while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
+    {
+        if ((errmsg > errbuf) || !isspace(*errmsg))
+        {
+            ++errmsg;
+            if ((*(errmsg - 1) == '\n') 
+                    || (errmsg >= errbuf + sizeof(errbuf) - 1))
+            {
+                while ((errmsg > errbuf) && isspace(*(errmsg - 1))) {
+                    --errmsg;
+                }
+                *errmsg = '\0';
+
+                /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
+                 * The event code in netmsg.dll is 3299
+                 */
+                ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
+                            3299, NULL, 9, 0, errarg, NULL);
+                errmsg = errbuf;
+            }
+        }
+    }
+
+    if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
+        apr_snprintf(errbuf, sizeof(errbuf),
+                     "Win32 error %d reading stderr pipe stream\r\n", 
+                     GetLastError());
+
+        ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
+                    3299, NULL, 9, 0, errarg, NULL);
+    }
+
+    CloseHandle(hPipeRead);
+    DeregisterEventSource(hEventSource);
+    CloseHandle(stderr_thread);
+    stderr_thread = NULL;
+    return 0;
+}
+
+
+void mpm_nt_eventlog_stderr_flush(void)
+{
+    HANDLE cleanup_thread = stderr_thread;
+
+    if (cleanup_thread) {
+        HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
+        fclose(stderr);
+        CloseHandle(hErr);
+        WaitForSingleObject(cleanup_thread, 30000);
+        CloseHandle(cleanup_thread);
+    }
+}
+
+
+void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
+{
+    SECURITY_ATTRIBUTES sa;
+    HANDLE hProc = GetCurrentProcess();
+    HANDLE hPipeRead = NULL;
+    HANDLE hPipeWrite = NULL;
+    HANDLE hDup = NULL;
+    DWORD  threadid;
+    int    fd;
+
+    display_name = argv0;
+
+    /* Create a pipe to send stderr messages to the system error log.
+     *
+     * _dup2() duplicates the write handle inheritable for us.
+     */
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = FALSE;
+    CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0); 
+    ap_assert(hPipeRead && hPipeWrite);
+
+    stderr_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
+    stderr_thread = CreateThread(NULL, 0, service_stderr_thread,
+                                 (LPVOID) hPipeRead, 0, &threadid);
+    ap_assert(stderr_ready && stderr_thread);
+
+    WaitForSingleObject(stderr_ready, INFINITE);
+
+    /* Flush stderr and unset its buffer, then commit and replace stderr.
+     * This is typically a noop for Win2K/XP since services with NULL std 
+     * handles [but valid FILE *'s, oddly enough], but is required 
+     * for NT 4.0 and to use this code outside of services.
+     */
+    fflush(stderr);
+    setvbuf(stderr, NULL, _IONBF, 0);
+    _commit(2 /* stderr */);
+    fd = _open_osfhandle((long) hPipeWrite, 
+                         _O_WRONLY | _O_BINARY);
+    _dup2(fd, 2);
+    _close(fd);
+    _setmode(2, _O_BINARY);
+
+    /* hPipeWrite was _close()'ed above, and _dup2()'ed
+     * to fd 2 creating a new, inherited Win32 handle.
+     * Recover that real handle from fd 2.
+     */
+    hPipeWrite = (HANDLE)_get_osfhandle(2);
+
+    SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
+
+    /* The code above _will_ corrupt the StdHandle... 
+     * and we must do so anyways.  We set this up only
+     * after we initialized the posix stderr API.
+     */
+    ap_open_stderr_log(p);
+}