From 208ae0c290cdc1d74c9286942860f1a64712f95b Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 22 Jan 2007 18:31:51 +0000
Subject: [PATCH] When system() fails in Win32, report it as an exception,
 print the exception value in hex, and give a URL where the value can be
 looked-up.

---
 src/backend/postmaster/postmaster.c | 12 ++++++++-
 src/include/port/win32.h            | 42 ++++++++++++++++++++++-------
 src/port/exec.c                     |  7 ++++-
 3 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f4c424c968..474e031111 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.508 2007/01/16 13:28:56 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.509 2007/01/22 18:31:51 momjian Exp $
  *
  * NOTES
  *
@@ -2421,6 +2421,7 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
 				(errmsg("%s (PID %d) exited with exit code %d",
 						procname, pid, WEXITSTATUS(exitstatus))));
 	else if (WIFSIGNALED(exitstatus))
+#ifndef WIN32
 		ereport(lev,
 
 		/*------
@@ -2428,6 +2429,15 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
 		  "server process" */
 				(errmsg("%s (PID %d) was terminated by signal %d",
 						procname, pid, WTERMSIG(exitstatus))));
+#else
+		ereport(lev,
+
+		/*------
+		  translator: %s is a noun phrase describing a child process, such as
+		  "server process" */
+				(errmsg("%s (PID %d) was terminated by exception %X\nSee http://source.winehq.org/source/include/ntstatus.h for a description\nof the hex value.",
+						procname, pid, WTERMSIG(exitstatus))));
+#endif
 	else
 		ereport(lev,
 
diff --git a/src/include/port/win32.h b/src/include/port/win32.h
index 22d71272d1..dc2219be16 100644
--- a/src/include/port/win32.h
+++ b/src/include/port/win32.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.65 2007/01/11 02:42:31 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.66 2007/01/22 18:31:51 momjian Exp $ */
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 #define WIN32_ONLY_COMPILER
@@ -115,16 +115,38 @@ int			semop(int semId, struct sembuf * sops, int flag);
 
 /*
  *	Signal stuff
- *	WIN32 doesn't have wait(), so the return value for children
- *	is simply the return value specified by the child, without
- *	any additional information on whether the child terminated
- *	on its own or via a signal.  These macros are also used
- *	to interpret the return value of system().
+ *
+ *	For WIN32, there is no wait() call so there are no wait() macros
+ *	to interpret the return value of system().  Instead, system()
+ *	return values < 0x100 are used for exit() termination, and higher
+ *	values are used to indicated non-exit() termination, which is
+ *	similar to a unix-style signal exit (think SIGSEGV ==
+ *	STATUS_ACCESS_VIOLATION).  Return values are broken up into groups:
+ *
+ *	http://msdn2.microsoft.com/en-gb/library/aa489609.aspx
+ *
+ *		NT_SUCCESS			0 - 0x3FFFFFFF
+ *		NT_INFORMATION		0x40000000 - 0x7FFFFFFF
+ *		NT_WARNING			0x80000000 - 0xBFFFFFFF
+ *		NT_ERROR			0xC0000000 - 0xFFFFFFFF
+ *
+ *	Effectively, we don't care on the severity of the return value from
+ *	system(), we just need to know if it was because of exit() or generated
+ *	by the system, and it seems values >= 0x100 are system-generated.
+ *	See this URL for a list of WIN32 STATUS_* values:
+ *
+ *		Wine (URL used in our error messages) -
+ *			http://source.winehq.org/source/include/ntstatus.h
+ *		Descriptions - http://www.comp.nus.edu.sg/~wuyongzh/my_doc/ntstatus.txt
+ *		MS SDK - http://www.nologs.com/ntstatus.html
+ *
+ *	Some day we might want to print descriptions for the most common
+ *	exceptions, rather than printing a URL.
  */
-#define WEXITSTATUS(w)	(w)
-#define WIFEXITED(w)	(true)
-#define WIFSIGNALED(w)	(false)
-#define WTERMSIG(w)		(0)
+#define WIFEXITED(w)    (((w) & 0xffffff00) == 0)
+#define WIFSIGNALED(w)  (!WIFEXITED(w))
+#define WEXITSTATUS(w)  (w)
+#define WTERMSIG(w)     (w)
 
 #define sigmask(sig) ( 1 << ((sig)-1) )
 
diff --git a/src/port/exec.c b/src/port/exec.c
index a8bd398460..4d54ed0e58 100644
--- a/src/port/exec.c
+++ b/src/port/exec.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/exec.c,v 1.44 2007/01/05 22:20:02 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/port/exec.c,v 1.45 2007/01/22 18:31:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -582,8 +582,13 @@ pclose_check(FILE *stream)
 		log_error(_("child process exited with exit code %d"),
 				  WEXITSTATUS(exitstatus));
 	else if (WIFSIGNALED(exitstatus))
+#ifndef WIN32
 		log_error(_("child process was terminated by signal %d"),
 				  WTERMSIG(exitstatus));
+#else
+		log_error(_("child process was terminated by exception %X\nSee http://source.winehq.org/source/include/ntstatus.h for a description\nof the hex value."),
+				  WTERMSIG(exitstatus));
+#endif
 	else
 		log_error(_("child process exited with unrecognized status %d"),
 				  exitstatus);
-- 
2.40.0