patch for distinguishing PG instances in event log
Hello,
I wrote and attached a patch for the TODO item below (which I proposed).
Allow multiple Postgres clusters running on the same machine to distinguish
themselves in the event log
http://archives.postgresql.org/pgsql-hackers/2011-03/msg01297.php
http://archives.postgresql.org/pgsql-hackers/2011-05/msg00574.php
I changed two things from the original proposal.
1. regsvr32.exe needs /n when you specify event source
I described the reason in src/bin/pgevent/pgevent.c.
2. I moved the article for event log registration to more suitable place
The traditional place and what I originally proposed were not best, because
those who don't build from source won't read those places.
I successfully tested event log registration/unregistration, event logging
with/without event_source parameter, and SHOWing event_source parameter with
psql on Windows Vista (32-bit). I would appreciate if someone could test it
on 64-bit Windows who has the 64-bit environment.
I'll add this patch to the first CommitFest of 9.2. Thank you in advance for
reviewing it.
Regards
MauMau
Attachments:
multi_event_source.patchapplication/octet-stream; name=multi_event_source.patchDownload
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
new file mode 100644
index 5d37065..46260d0
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** local0.* /var/log/postgresql
*** 2949,2954 ****
--- 2949,2961 ----
to the <application>syslog</application> daemon's configuration file
to make it work.
</para>
+ <para>
+ On Windows, you need to register an event source
+ and its library with the operating system in order
+ to make use of the <systemitem>eventlog</systemitem> option for
+ <varname>log_destination</>.
+ See <xref linkend="event-log-registration"> for details.
+ </para>
</note>
</listitem>
</varlistentry>
*************** local0.* /var/log/postgresql
*** 3189,3194 ****
--- 3196,3219 ----
<productname>PostgreSQL</productname> messages in
<application>syslog</application> logs. The default is
<literal>postgres</literal>.
+ This parameter can only be set in the <filename>postgresql.conf</>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="guc-event-source" xreflabel="event_source">
+ <term><varname>event_source</varname> (<type>string</type>)</term>
+ <indexterm>
+ <primary><varname>event_source</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ When logging to <application>event log</> is enabled, this parameter
+ determines the program name used to identify
+ <productname>PostgreSQL</productname> messages in
+ <application>event log</application>. The default is
+ <literal>PostgreSQL</literal>.
This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line.
</para>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
new file mode 100644
index 96387bd..262b91a
*** a/doc/src/sgml/installation.sgml
--- b/doc/src/sgml/installation.sgml
*************** PostgreSQL, contrib and HTML documentati
*** 1551,1569 ****
</procedure>
<formalpara>
- <title>Registering <application>eventlog</> on <systemitem
- class="osname">Windows</>:</title>
- <para>
- To register a <systemitem class="osname">Windows</> <application>eventlog</>
- library with the operating system, issue this command after installation:
- <screen>
- <userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
- </screen>
- This creates registry entries used by the event viewer.
- </para>
- </formalpara>
-
- <formalpara>
<title>Uninstallation:</title>
<para>
To undo the installation use the command <command>gmake
--- 1551,1556 ----
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
new file mode 100644
index d18ba79..9a8a22d
*** a/doc/src/sgml/runtime.sgml
--- b/doc/src/sgml/runtime.sgml
*************** ssh -L 63333:db.foo.com:5432 joe@shell.f
*** 2294,2297 ****
--- 2294,2347 ----
</sect1>
+ <sect1 id="event-log-registration">
+ <title>Registering <application>Event Log</> on <systemitem
+ class="osname">Windows</></title>
+
+ <indexterm zone="event-log-registration">
+ <primary>event log</primary>
+ <secondary>event log</secondary>
+ </indexterm>
+
+ <para>
+ To register a <systemitem class="osname">Windows</> <application>event log</>
+ library with the operating system, issue this command:
+ <screen>
+ <userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ This creates registry entries used by the event viewer, under the default event
+ source named "PostgreSQL".
+ </para>
+
+ <para>
+ You can specify the event source name with /i option. In this case, -n option
+ is necessary, too:
+ <screen>
+ <userinput>regsvr32 /n /i:<replaceable>event_source_name</>
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ You also need to set <xref linkend="guc-event-source"> in
+ <filename>postgresql.conf</filename>. Note that the event source specification
+ only takes effect for the database server. Other applications like
+ <command>pg_ctl</command> always use "PostgreSQL" event source.
+ </para>
+
+ <para>
+ To unregister the <application>event log</> library from
+ the operating system, issue this command:
+ <screen>
+ <userinput>regsvr32 /u [/i:<replaceable>event_source_name</>]
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ </para>
+
+ <note>
+ <para>
+ To enable event logging in the database server, modify
+ <xref linkend="guc-log-destination"> to include
+ <systemitem>eventlog</systemitem> in <filename>postgresql.conf</filename>.
+ </para>
+ </note>
+ </sect1>
+
</chapter>
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
new file mode 100644
index 337b875..0744987
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
*************** static void write_syslog(int level, cons
*** 122,127 ****
--- 122,129 ----
static void write_console(const char *line, int len);
#ifdef WIN32
+ static char *event_source = NULL;
+
static void write_eventlog(int level, const char *line, int len);
#endif
*************** write_syslog(int level, const char *line
*** 1633,1638 ****
--- 1635,1655 ----
#endif /* HAVE_SYSLOG */
#ifdef WIN32
+
+ /*
+ * Set or update the parameters for event log logging
+ */
+ void
+ set_eventlog_parameters(const char *source)
+ {
+ if (event_source == NULL || strcmp(event_source, source) != 0)
+ {
+ if (event_source)
+ free(event_source);
+ event_source = strdup(source);
+ }
+ }
+
/*
* Write a message line to the windows event log
*/
*************** write_eventlog(int level, const char *li
*** 1645,1651 ****
if (evtHandle == INVALID_HANDLE_VALUE)
{
! evtHandle = RegisterEventSource(NULL, "PostgreSQL");
if (evtHandle == NULL)
{
evtHandle = INVALID_HANDLE_VALUE;
--- 1662,1668 ----
if (evtHandle == INVALID_HANDLE_VALUE)
{
! evtHandle = RegisterEventSource(NULL, event_source ? event_source : "PostgreSQL");
if (evtHandle == NULL)
{
evtHandle = INVALID_HANDLE_VALUE;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index 92391ed..07ce52d
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static int syslog_facility = 0;
*** 175,180 ****
--- 175,183 ----
static void assign_syslog_facility(int newval, void *extra);
static void assign_syslog_ident(const char *newval, void *extra);
+ #ifdef WIN32
+ static void assign_event_source(const char *newval, void *extra);
+ #endif
static void assign_session_replication_role(int newval, void *extra);
static bool check_temp_buffers(int *newval, void **extra, GucSource source);
static bool check_phony_autocommit(bool *newval, void **extra, GucSource source);
*************** int tcp_keepalives_count;
*** 449,454 ****
--- 452,460 ----
static char *log_destination_string;
static char *syslog_ident_str;
+ #ifdef WIN32
+ static char *event_source_str;
+ #endif
static bool phony_autocommit;
static bool session_auth_is_superuser;
static double phony_random_seed;
*************** static struct config_string ConfigureNam
*** 2822,2827 ****
--- 2828,2846 ----
NULL, assign_syslog_ident, NULL
},
+ #ifdef WIN32
+ {
+ {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
+ gettext_noop("Sets the program name used to identify PostgreSQL "
+ "messages in event log."),
+ NULL
+ },
+ &event_source_str,
+ "PostgreSQL",
+ NULL, assign_event_source, NULL
+ },
+ #endif
+
{
{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
*************** assign_syslog_ident(const char *newval,
*** 8213,8218 ****
--- 8232,8245 ----
#endif
/* Without syslog support, it will always be set to "none", so ignore */
}
+
+ #ifdef WIN32
+ static void
+ assign_event_source(const char *newval, void *extra)
+ {
+ set_eventlog_parameters(newval);
+ }
+ #endif
static void
diff --git a/src/bin/pgevent/pgevent.c b/src/bin/pgevent/pgevent.c
new file mode 100644
index 1fcde86..402d00a
*** a/src/bin/pgevent/pgevent.c
--- b/src/bin/pgevent/pgevent.c
***************
*** 15,31 ****
--- 15,75 ----
#include <windows.h>
#include <olectl.h>
#include <string.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <Tchar.h>
/* Global variables */
HANDLE g_module = NULL; /* hModule of DLL */
+ /*
+ * The event source is stored as a registry key.
+ * The maximum length of a registry key is 255 characters.
+ * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx
+ */
+ _TCHAR event_source[256] = _T("PostgreSQL");
/* Prototypes */
+ HRESULT DllInstall(BOOL bInstall, __in_opt LPCWSTR pszCmdLine);
STDAPI
DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
/*
+ * DllInstall --- Passes the command line argument to DLL
+ */
+
+ HRESULT
+ DllInstall(BOOL bInstall,
+ __in_opt LPCWSTR pszCmdLine)
+ {
+ #ifndef _UNICODE
+ size_t ret;
+ #endif
+
+ if (pszCmdLine && *pszCmdLine != '\0')
+ #ifdef _UNICODE
+ _tcsncpy(event_source, pszCmdLine, sizeof(event_source));
+ #else
+ wcstombs_s(&ret, event_source, sizeof(event_source),
+ pszCmdLine, sizeof(event_source));
+ #endif
+
+ /*
+ * This is an ugry part due to the strange behavior of "regsvr32 /i".
+ * When installing, regsvr32 calls DllRegisterServer before DllInstall.
+ * When uninstalling (i.e. "regsvr32 /u /i"), on the other hand,
+ * regsvr32 calls DllInstall and then DllUnregisterServer as expected.
+ * This strange behavior forces us to specify -n (i.e. "regsvr32 /n /i").
+ * Without -n, DllRegisterServer called before DllInstall would
+ * mistakenly overwrite the default "PostgreSQL" event source registration.
+ */
+ if (bInstall)
+ DllRegisterServer();
+ return S_OK;
+ }
+
+ /*
* DllRegisterServer --- Instructs DLL to create its registry entries
*/
*************** DllRegisterServer(void)
*** 35,40 ****
--- 79,85 ----
HKEY key;
DWORD data;
char buffer[_MAX_PATH];
+ _TCHAR key_name[400];
/* Set the name of DLL full path name. */
if (!GetModuleFileName((HMODULE) g_module, buffer, sizeof(buffer)))
*************** DllRegisterServer(void)
*** 47,53 ****
* Add PostgreSQL source name as a subkey under the Application key in the
* EventLog registry key.
*/
! if (RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL", &key))
{
MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
--- 92,101 ----
* Add PostgreSQL source name as a subkey under the Application key in the
* EventLog registry key.
*/
! _sntprintf(key_name, sizeof(key_name),
! _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"),
! event_source);
! if (RegCreateKey(HKEY_LOCAL_MACHINE, key_name, &key))
{
MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
*************** DllRegisterServer(void)
*** 90,101 ****
STDAPI
DllUnregisterServer(void)
{
/*
* Remove PostgreSQL source name as a subkey under the Application key in
* the EventLog registry key.
*/
! if (RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL"))
{
MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
--- 138,154 ----
STDAPI
DllUnregisterServer(void)
{
+ _TCHAR key_name[400];
+
/*
* Remove PostgreSQL source name as a subkey under the Application key in
* the EventLog registry key.
*/
! _sntprintf(key_name, sizeof(key_name),
! _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s"),
! event_source);
! if (RegDeleteKey(HKEY_LOCAL_MACHINE, key_name))
{
MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
diff --git a/src/bin/pgevent/pgevent.def b/src/bin/pgevent/pgevent.def
new file mode 100644
index 21bab7a..6b4d44a
*** a/src/bin/pgevent/pgevent.def
--- b/src/bin/pgevent/pgevent.def
***************
*** 2,4 ****
--- 2,5 ----
EXPORTS
DllUnregisterServer ;
DllRegisterServer ;
+ DllInstall ;
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
new file mode 100644
index 4a3bd02..48bc784
*** a/src/include/utils/elog.h
--- b/src/include/utils/elog.h
*************** extern void DebugFileOpen(void);
*** 353,358 ****
--- 353,362 ----
extern char *unpack_sql_state(int sql_state);
extern bool in_error_recursion_trouble(void);
+ #ifdef WIN32
+ extern void set_eventlog_parameters(const char *source);
+ #endif
+
#ifdef HAVE_SYSLOG
extern void set_syslog_parameters(const char *ident, int facility);
#endif
All,
Merlin volunteered to review this patch and has not turned in a review.
Can someone who is Windows-saavy pitch in and review it ASAP?
I wrote and attached a patch for the TODO item below (which I proposed).
Allow multiple Postgres clusters running on the same machine to
distinguish themselves in the event log
http://archives.postgresql.org/pgsql-hackers/2011-03/msg01297.php
http://archives.postgresql.org/pgsql-hackers/2011-05/msg00574.php
--
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com
2011/5/26 MauMau <maumau307@gmail.com>:
Hello,
I wrote and attached a patch for the TODO item below (which I proposed).
Allow multiple Postgres clusters running on the same machine to distinguish
themselves in the event log
http://archives.postgresql.org/pgsql-hackers/2011-03/msg01297.php
http://archives.postgresql.org/pgsql-hackers/2011-05/msg00574.phpI changed two things from the original proposal.
1. regsvr32.exe needs /n when you specify event source
I described the reason in src/bin/pgevent/pgevent.c.2. I moved the article for event log registration to more suitable place
The traditional place and what I originally proposed were not best, because
those who don't build from source won't read those places.I successfully tested event log registration/unregistration, event logging
with/without event_source parameter, and SHOWing event_source parameter with
psql on Windows Vista (32-bit). I would appreciate if someone could test it
on 64-bit Windows who has the 64-bit environment.I'll add this patch to the first CommitFest of 9.2. Thank you in advance for
reviewing it.
+ <para>
+ On Windows, you need to register an event source
+ and its library with the operating system in order
+ to make use of the <systemitem>eventlog</systemitem> option for
+ <varname>log_destination</>.
+ See <xref linkend="event-log-registration"> for details.
+ </para>
* This part is not strictly correct - you don't *need* to do that, it
just makes things look nicer, no?
* Also, what is the use for set_eventlog_parameters()? It's just a
string variable, it shuold work without it.
* We these days avoid #ifdef'ing gucs just because they are not on
that platform - so the list is consistent. The guc should be available
on non-windows platforms as well.
* The guc also needs to go in postgresql.conf.sample
* We never build in unicode mode, so all those checks are unnecessary.
* Are we really allowed to call MessageBox in DlLRegisterService?
Won't that break badly in cases like silent installs?
Attached is an updated patch, which doesn't work yet. I believe the
changes to the backend are correct, but probably some of the cleanups
and changes in the dll are incorrect, because I seem to be unable to
register either the default or a custom handler so far.
--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/
Attachments:
multi_event_source_2.patchtext/x-patch; charset=US-ASCII; name=multi_event_source_2.patchDownload
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 842558d..583a5c9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2975,6 +2975,13 @@ local0.* /var/log/postgresql
to the <application>syslog</application> daemon's configuration file
to make it work.
</para>
+ <para>
+ On Windows, you need to register an event source
+ and its library with the operating system in order
+ to make use of the <systemitem>eventlog</systemitem> option for
+ <varname>log_destination</>.
+ See <xref linkend="event-log-registration"> for details.
+ </para>
</note>
</listitem>
</varlistentry>
@@ -3221,6 +3228,24 @@ local0.* /var/log/postgresql
</listitem>
</varlistentry>
+ <varlistentry id="guc-event-source" xreflabel="event_source">
+ <term><varname>event_source</varname> (<type>string</type>)</term>
+ <indexterm>
+ <primary><varname>event_source</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ When logging to <application>event log</> is enabled, this parameter
+ determines the program name used to identify
+ <productname>PostgreSQL</productname> messages in
+ <application>event log</application>. The default is
+ <literal>PostgreSQL</literal>.
+ This parameter can only be set in the <filename>postgresql.conf</>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect2>
<sect2 id="runtime-config-logging-when">
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 0410cff..41b9009 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1552,19 +1552,6 @@ PostgreSQL, contrib and HTML documentation successfully made. Ready to install.
</procedure>
<formalpara>
- <title>Registering <application>eventlog</> on <systemitem
- class="osname">Windows</>:</title>
- <para>
- To register a <systemitem class="osname">Windows</> <application>eventlog</>
- library with the operating system, issue this command after installation:
-<screen>
-<userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
-</screen>
- This creates registry entries used by the event viewer.
- </para>
- </formalpara>
-
- <formalpara>
<title>Uninstallation:</title>
<para>
To undo the installation use the command <command>gmake
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index ef83206..bfbb641 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -2294,4 +2294,54 @@ ssh -L 63333:db.foo.com:5432 joe@shell.foo.com
</sect1>
+ <sect1 id="event-log-registration">
+ <title>Registering <application>Event Log</> on <systemitem
+ class="osname">Windows</></title>
+
+ <indexterm zone="event-log-registration">
+ <primary>event log</primary>
+ <secondary>event log</secondary>
+ </indexterm>
+
+ <para>
+ To register a <systemitem class="osname">Windows</> <application>event log</>
+ library with the operating system, issue this command:
+<screen>
+<userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
+</screen>
+ This creates registry entries used by the event viewer, under the default event
+ source named "PostgreSQL".
+ </para>
+
+ <para>
+ You can specify the event source name with /i option. In this case, -n option
+ is necessary, too:
+<screen>
+<userinput>regsvr32 /n /i:<replaceable>event_source_name</>
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+</screen>
+ You also need to set <xref linkend="guc-event-source"> in
+ <filename>postgresql.conf</filename>. Note that the event source specification
+ only takes effect for the database server. Other applications like
+ <command>pg_ctl</command> always use "PostgreSQL" event source.
+ </para>
+
+ <para>
+ To unregister the <application>event log</> library from
+ the operating system, issue this command:
+<screen>
+<userinput>regsvr32 /u [/i:<replaceable>event_source_name</>]
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+</screen>
+ </para>
+
+ <note>
+ <para>
+ To enable event logging in the database server, modify
+ <xref linkend="guc-log-destination"> to include
+ <systemitem>eventlog</systemitem> in <filename>postgresql.conf</filename>.
+ </para>
+ </note>
+ </sect1>
+
</chapter>
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 337b875..1708869 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -122,6 +122,7 @@ static void write_syslog(int level, const char *line);
static void write_console(const char *line, int len);
#ifdef WIN32
+extern char *event_source; /* guc */
static void write_eventlog(int level, const char *line, int len);
#endif
@@ -1633,6 +1634,7 @@ write_syslog(int level, const char *line)
#endif /* HAVE_SYSLOG */
#ifdef WIN32
+
/*
* Write a message line to the windows event log
*/
@@ -1645,7 +1647,7 @@ write_eventlog(int level, const char *line, int len)
if (evtHandle == INVALID_HANDLE_VALUE)
{
- evtHandle = RegisterEventSource(NULL, "PostgreSQL");
+ evtHandle = RegisterEventSource(NULL, event_source ? event_source : "PostgreSQL");
if (evtHandle == NULL)
{
evtHandle = INVALID_HANDLE_VALUE;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 5841631..b6ab341 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -411,6 +411,7 @@ bool log_executor_stats = false;
bool log_statement_stats = false; /* this is sort of all three
* above together */
bool log_btree_build_stats = false;
+char *event_source;
bool check_function_bodies = true;
bool default_with_oids = false;
@@ -2815,6 +2816,17 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
+ gettext_noop("Sets the application name used to identify"
+ "PostgreSQL messages in the event log."),
+ NULL
+ },
+ &event_source,
+ "PostgreSQL",
+ NULL, NULL, NULL
+ },
+
+ {
{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
NULL,
@@ -8214,7 +8226,6 @@ assign_syslog_ident(const char *newval, void *extra)
/* Without syslog support, it will always be set to "none", so ignore */
}
-
static void
assign_session_replication_role(int newval, void *extra)
{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 9403293..f161435 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -309,6 +309,8 @@
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
+# This is relevant only when logging to eventlog:
+#event_source = 'PostgreSQL'
# - When to Log -
diff --git a/src/bin/pgevent/pgevent.c b/src/bin/pgevent/pgevent.c
index 1fcde86..d186e16 100644
--- a/src/bin/pgevent/pgevent.c
+++ b/src/bin/pgevent/pgevent.c
@@ -15,17 +15,52 @@
#include <windows.h>
#include <olectl.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
/* Global variables */
HANDLE g_module = NULL; /* hModule of DLL */
+/*
+ * The event source is stored as a registry key.
+ * The maximum length of a registry key is 255 characters.
+ * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx
+ */
+char event_source[256];
+
/* Prototypes */
-STDAPI
-DllRegisterServer(void);
+HRESULT DllInstall(BOOL bInstall, __in_opt LPCWSTR pszCmdLine);
+STDAPI DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
/*
+ * DllInstall --- Passes the command line argument to DLL
+ */
+HRESULT
+DllInstall(BOOL bInstall,
+ __in_opt LPCWSTR pszCmdLine)
+{
+ if (pszCmdLine && *pszCmdLine != '\0')
+ strncpy(event_source, sizeof(event_source), pszCmdLine);
+ else
+ strcpy(event_source, "PostgreSQL");
+
+ /*
+ * This is an ugry part due to the strange behavior of "regsvr32 /i".
+ * When installing, regsvr32 calls DllRegisterServer before DllInstall.
+ * When uninstalling (i.e. "regsvr32 /u /i"), on the other hand,
+ * regsvr32 calls DllInstall and then DllUnregisterServer as expected.
+ * This strange behavior forces us to specify -n (i.e. "regsvr32 /n /i").
+ * Without -n, DllRegisterServer called before DllInstall would
+ * mistakenly overwrite the default "PostgreSQL" event source registration.
+ */
+ if (bInstall)
+ DllRegisterServer();
+ return S_OK;
+}
+
+/*
* DllRegisterServer --- Instructs DLL to create its registry entries
*/
@@ -35,6 +70,7 @@ DllRegisterServer(void)
HKEY key;
DWORD data;
char buffer[_MAX_PATH];
+ char key_name[400];
/* Set the name of DLL full path name. */
if (!GetModuleFileName((HMODULE) g_module, buffer, sizeof(buffer)))
@@ -47,7 +83,10 @@ DllRegisterServer(void)
* Add PostgreSQL source name as a subkey under the Application key in the
* EventLog registry key.
*/
- if (RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL", &key))
+ _snprintf(key_name, sizeof(key_name),
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
+ event_source);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, key_name, &key))
{
MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
@@ -90,12 +129,16 @@ DllRegisterServer(void)
STDAPI
DllUnregisterServer(void)
{
+ char key_name[400];
+
/*
* Remove PostgreSQL source name as a subkey under the Application key in
* the EventLog registry key.
*/
-
- if (RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL"))
+ _snprintf(key_name, sizeof(key_name),
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
+ event_source);
+ if (RegDeleteKey(HKEY_LOCAL_MACHINE, key_name))
{
MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
@@ -113,6 +156,8 @@ DllMain(HANDLE hModule,
LPVOID lpReserved
)
{
+ memset(event_source, 0, sizeof(event_source));
+
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
g_module = hModule;
return TRUE;
diff --git a/src/bin/pgevent/pgevent.def b/src/bin/pgevent/pgevent.def
index 21bab7a..6b4d44a 100644
--- a/src/bin/pgevent/pgevent.def
+++ b/src/bin/pgevent/pgevent.def
@@ -2,3 +2,4 @@
EXPORTS
DllUnregisterServer ;
DllRegisterServer ;
+ DllInstall ;
Magnus,
Thank you for reviewing my patch. I'm going to modify the patch according to
your comments and re-submit it. Before that, I'd like to discuss some points
and get your agreement.
From: "Magnus Hagander" <magnus@hagander.net>
+ <para> + On Windows, you need to register an event source + and its library with the operating system in order + to make use of the <systemitem>eventlog</systemitem> option for + <varname>log_destination</>. + See <xref linkend="event-log-registration"> for details. + </para>* This part is not strictly correct - you don't *need* to do that, it
just makes things look nicer, no?
How about the following statement? Is it better to say "correctly" instead
of "cleanly"?
--------------------------------------------------
On Windows, when you use the eventlog option for log_destination, you need
to register an event sourceand its library with the operating system so that
the Windows Event Viewer can display event log messages cleanly.
--------------------------------------------------
* Also, what is the use for set_eventlog_parameters()? It's just a
string variable, it shuold work without it.
Yes, exactly. I'll follow your modification.
* We these days avoid #ifdef'ing gucs just because they are not on
that platform - so the list is consistent. The guc should be available
on non-windows platforms as well.
I see. When I saw syslog_ident not being #ifndef WIN32'ed, I thought that
was because syslog might be available on Cygwin or MinGW. Anyway, I'll take
your modification.
* The guc also needs to go in postgresql.conf.sample
I missed this completely.
* Are we really allowed to call MessageBox in DlLRegisterService?
Won't that break badly in cases like silent installs?
It seems that the only way to notify the error is MessageBox. Printing to
stdout/stderr does not show any messages on the command prompt. I guess
that's why the original author of pgevent.c used MessageBox.
We cannot know within the DLL if /s (silent) switch was specified to
regsvr32.exe. If we want to suppress MessageBox during silent installs, it
seems that we need to know the silent install by an environment variable or
so. That is:
C:\> set PGSILENT=true
C:\> regsvr32.exe ...
* We never build in unicode mode, so all those checks are unnecessary.
Attached is an updated patch, which doesn't work yet. I believe the
changes to the backend are correct, but probably some of the cleanups
and changes in the dll are incorrect, because I seem to be unable to
register either the default or a custom handler so far.
The cause of the problem you are encountering is here:
+ if (pszCmdLine && *pszCmdLine != '\0')
+ strncpy(event_source, sizeof(event_source), pszCmdLine);
+ else
+ strcpy(event_source, "PostgreSQL");
DllInstall() always receives the /i argument in UTF-16. str... functions
like strncpy() cannot be used for handling UTF-16 strings. For example, when
you run "regsvr32.exe /i:abc ...", DllInstall's pszCmdLine value becomes
"a\0b\0c\0". So, strncpy() just copies "a". This is the reason why you
cannot register the custom event source.
The reason why you cannot register the default event source (i.e. running
regsvr32 without /i) is that you memset()ed event_source in DllMain() and
set "PostgreSQL" to it in DllInstall(). DllInstall() is not called when /i
is not specified. So, event_source remains empty.
To solve the problem, we need to use wcstombs_s() instead of strncpy(), and
initialize event_source to "PostgreSQL" when it is defined.
Regards
MauMau
On Fri, Jul 15, 2011 at 15:03, MauMau <maumau307@gmail.com> wrote:
Magnus,
Thank you for reviewing my patch. I'm going to modify the patch according to
your comments and re-submit it. Before that, I'd like to discuss some points
and get your agreement.
Ok, please do. If you want to, you can work off my git branch at
http://github.com/mhagander/postgres (branch multievent).
From: "Magnus Hagander" <magnus@hagander.net>
+ <para> + On Windows, you need to register an event source + and its library with the operating system in order + to make use of the <systemitem>eventlog</systemitem> option for + <varname>log_destination</>. + See <xref linkend="event-log-registration"> for details. + </para>* This part is not strictly correct - you don't *need* to do that, it
just makes things look nicer, no?How about the following statement? Is it better to say "correctly" instead
of "cleanly"?--------------------------------------------------
On Windows, when you use the eventlog option for log_destination, you need
to register an event sourceand its library with the operating system so that
the Windows Event Viewer can display event log messages cleanly.
--------------------------------------------------
Replace "need" with "should" and I'm happy with that.
* Also, what is the use for set_eventlog_parameters()? It's just a
string variable, it shuold work without it.Yes, exactly. I'll follow your modification.
* We these days avoid #ifdef'ing gucs just because they are not on
that platform - so the list is consistent. The guc should be available
on non-windows platforms as well.I see. When I saw syslog_ident not being #ifndef WIN32'ed, I thought that
was because syslog might be available on Cygwin or MinGW. Anyway, I'll take
your modification.
Nope, it used to be #ifdefed on HAVE_SYSLOG, but we changed that a
while ago for consistency.
* The guc also needs to go in postgresql.conf.sample
I missed this completely.
* Are we really allowed to call MessageBox in DlLRegisterService?
Won't that break badly in cases like silent installs?It seems that the only way to notify the error is MessageBox. Printing to
stdout/stderr does not show any messages on the command prompt. I guess
that's why the original author of pgevent.c used MessageBox.
oh, we're already using messagebox.. I must've been confused, I
thought it was new. Heck, it might even be me who wrote that :O
We cannot know within the DLL if /s (silent) switch was specified to
regsvr32.exe. If we want to suppress MessageBox during silent installs, it
seems that we need to know the silent install by an environment variable or
so. That is:C:\> set PGSILENT=true
C:\> regsvr32.exe ...
I think if we're not Ok with messagebox, then we should just write it
to the eventlog. However, given that we have been using messagebox
before and had no complaints, I should withdraw my complaint for now -
keep using messagebox like the surrounding code. We can attack the
potential issue of that in a separate patch later.
* We never build in unicode mode, so all those checks are unnecessary.
Attached is an updated patch, which doesn't work yet. I believe the
changes to the backend are correct, but probably some of the cleanups
and changes in the dll are incorrect, because I seem to be unable to
register either the default or a custom handler so far.The cause of the problem you are encountering is here:
+ if (pszCmdLine && *pszCmdLine != '\0') + strncpy(event_source, sizeof(event_source), pszCmdLine); + else + strcpy(event_source, "PostgreSQL");DllInstall() always receives the /i argument in UTF-16. str... functions
like strncpy() cannot be used for handling UTF-16 strings. For example, when
you run "regsvr32.exe /i:abc ...", DllInstall's pszCmdLine value becomes
"a\0b\0c\0". So, strncpy() just copies "a". This is the reason why you
cannot register the custom event source.
Oh, it gets it as UTF-16 even when not in unicode mode. I see - yeah,
I didn't have time to read up on the calling conventions properly.
The reason why you cannot register the default event source (i.e. running
regsvr32 without /i) is that you memset()ed event_source in DllMain() and
set "PostgreSQL" to it in DllInstall(). DllInstall() is not called when /i
is not specified. So, event_source remains empty.To solve the problem, we need to use wcstombs_s() instead of strncpy(), and
initialize event_source to "PostgreSQL" when it is defined.
Ok, seems reasonable.
--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/