*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
***************
*** 386,394 **** typedef struct
--- 386,396 ----
  	HANDLE		waitHandle;
  	HANDLE		procHandle;
  	DWORD		procId;
+ 	HANDLE		startupCompletedEvent;
  }	win32_deadchild_waitinfo;
  
  HANDLE		PostmasterHandle;
+ static HANDLE	StartupCompletedEvent;
  #endif
  
  static pid_t backend_forkexec(Port *port);
***************
*** 440,445 **** typedef struct
--- 442,448 ----
  	bool		redirection_done;
  #ifdef WIN32
  	HANDLE		PostmasterHandle;
+ 	HANDLE		StartupCompletedEvent;
  	HANDLE		initial_signal_pipe;
  	HANDLE		syslogPipe[2];
  #else
***************
*** 3757,3762 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3760,3777 ----
  	si.cb = sizeof(si);
  
  	/*
+ 	 * Create an event used to verify that the child started properly.
+ 	 */
+ 	StartupCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ 	if (!StartupCompletedEvent)
+ 	{
+ 		ereport(LOG,
+ 				(errmsg_internal("could not create StartupCompletedEvent: error code %d",
+ 								 (int) GetLastError())));
+ 		return -1;
+ 	}
+ 
+ 	/*
  	 * Create the subprocess in a suspended state. This will be resumed later,
  	 * once we have written out the parameter file.
  	 */
***************
*** 3765,3770 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3780,3786 ----
  	{
  		elog(LOG, "CreateProcess call failed: %m (error code %d)",
  			 (int) GetLastError());
+ 		CloseHandle(StartupCompletedEvent);
  		return -1;
  	}
  
***************
*** 3780,3785 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3796,3802 ----
  									 (int) GetLastError())));
  		CloseHandle(pi.hProcess);
  		CloseHandle(pi.hThread);
+ 		CloseHandle(StartupCompletedEvent);
  		return -1;				/* log made by save_backend_variables */
  	}
  
***************
*** 3807,3812 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3824,3830 ----
  									 (int) GetLastError())));
  		CloseHandle(pi.hProcess);
  		CloseHandle(pi.hThread);
+ 		CloseHandle(StartupCompletedEvent);
  		return -1;				/* logging done made by
  								 * pgwin32_ReserveSharedMemoryRegion() */
  	}
***************
*** 3825,3834 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3843,3854 ----
  									 (int) GetLastError())));
  			CloseHandle(pi.hProcess);
  			CloseHandle(pi.hThread);
+ 			CloseHandle(StartupCompletedEvent);
  			return -1;
  		}
  		CloseHandle(pi.hProcess);
  		CloseHandle(pi.hThread);
+ 		CloseHandle(StartupCompletedEvent);
  		ereport(LOG,
  				(errmsg_internal("could not resume thread of unstarted process: error code %d",
  								 (int) GetLastError())));
***************
*** 3851,3856 **** internal_forkexec(int argc, char *argv[], Port *port)
--- 3871,3877 ----
  
  	childinfo->procHandle = pi.hProcess;
  	childinfo->procId = pi.dwProcessId;
+ 	childinfo->startupCompletedEvent = StartupCompletedEvent;
  
  	if (!RegisterWaitForSingleObject(&childinfo->waitHandle,
  									 pi.hProcess,
***************
*** 3920,3925 **** SubPostmasterMain(int argc, char *argv[])
--- 3941,3955 ----
  	read_backend_variables(argv[2], &port);
  
  	/*
+ 	 * Flag that we are running, as soon as possible, for detecting
+ 	 * processes that die on startup before our code has a chance
+ 	 * to do anything.
+ 	 */
+ #ifdef WIN32
+ 	SetEvent(StartupCompletedEvent);
+ #endif
+ 
+ 	/*
  	 * Set up memory area for GSS information. Mirrors the code in ConnCreate
  	 * for the non-exec case.
  	 */
***************
*** 4603,4609 **** extern pgsocket pgStatSock;
  #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
  #define read_inheritable_socket(dest, src) (*(dest) = *(src))
  #else
! static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
  static bool write_inheritable_socket(InheritableSocket * dest, SOCKET src,
  						 pid_t childPid);
  static void read_inheritable_socket(SOCKET * dest, InheritableSocket * src);
--- 4633,4639 ----
  #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
  #define read_inheritable_socket(dest, src) (*(dest) = *(src))
  #else
! static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child, bool close);
  static bool write_inheritable_socket(InheritableSocket * dest, SOCKET src,
  						 pid_t childPid);
  static void read_inheritable_socket(SOCKET * dest, InheritableSocket * src);
***************
*** 4656,4662 **** save_backend_variables(BackendParameters * param, Port *port,
  	param->PostmasterHandle = PostmasterHandle;
  	if (!write_duplicated_handle(&param->initial_signal_pipe,
  								 pgwin32_create_signal_listener(childPid),
! 								 childProcess))
  		return false;
  #endif
  
--- 4686,4696 ----
  	param->PostmasterHandle = PostmasterHandle;
  	if (!write_duplicated_handle(&param->initial_signal_pipe,
  								 pgwin32_create_signal_listener(childPid),
! 								 childProcess, true))
! 		return false;
! 	if (!write_duplicated_handle(&param->StartupCompletedEvent,
! 								 StartupCompletedEvent,
! 								 childProcess, false))
  		return false;
  #endif
  
***************
*** 4676,4686 **** save_backend_variables(BackendParameters * param, Port *port,
  /*
   * Duplicate a handle for usage in a child process, and write the child
   * process instance of the handle to the parameter file.
   */
  static bool
! write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
  {
  	HANDLE		hChild = INVALID_HANDLE_VALUE;
  
  	if (!DuplicateHandle(GetCurrentProcess(),
  						 src,
--- 4710,4723 ----
  /*
   * Duplicate a handle for usage in a child process, and write the child
   * process instance of the handle to the parameter file.
+  * If the close parameter is set to true, the handle will be set to be
+  * closed in the postmaster once it's duplicated.
   */
  static bool
! write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess, bool close)
  {
  	HANDLE		hChild = INVALID_HANDLE_VALUE;
+ 	int			closeflag = close ? DUPLICATE_CLOSE_SOURCE : 0;
  
  	if (!DuplicateHandle(GetCurrentProcess(),
  						 src,
***************
*** 4688,4694 **** write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
  						 &hChild,
  						 0,
  						 TRUE,
! 						 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
  	{
  		ereport(LOG,
  				(errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %d",
--- 4725,4731 ----
  						 &hChild,
  						 0,
  						 TRUE,
! 						 closeflag | DUPLICATE_SAME_ACCESS))
  	{
  		ereport(LOG,
  				(errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %d",
***************
*** 4868,4873 **** restore_backend_variables(BackendParameters * param, Port *port)
--- 4905,4911 ----
  
  #ifdef WIN32
  	PostmasterHandle = param->PostmasterHandle;
+ 	StartupCompletedEvent = param->StartupCompletedEvent;
  	pgwin32_initial_signal_pipe = param->initial_signal_pipe;
  #endif
  
***************
*** 4944,4949 **** win32_waitpid(int *exitstatus)
--- 4982,4990 ----
  /*
   * Note! Code below executes on a thread pool! All operations must
   * be thread safe! Note that elog() and friends must *not* be used.
+  * Instead, use write_stderr() which will write the log to stderr
+  * when running on the console, or the eventlog when running as
+  * a service.
   */
  static void WINAPI
  pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
***************
*** 4970,4975 **** pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
--- 5011,5038 ----
  		exitcode = 255;
  	}
  
+ 	/*
+ 	 * Did the process "fail before it started"?
+ 	 *
+ 	 * When the process has reached "runnable state", we will set the
+ 	 * event in childinfo->startupCompletedEvent (using the duplicated
+ 	 * handle that exists in the child process). If this event is
+ 	 * not set, it means the process died before we got control of it,
+ 	 * due to something like third party DLL failing to load or running
+ 	 * out of desktop heap space.
+ 	 *
+ 	 * Don't treat this a fatal error requiring a restart. Instead,
+ 	 * just log the fact and then post an exitcode indicating that
+ 	 * the backend exited with a regular fatal error (exit code 1).
+ 	 */
+ 	if (WaitForSingleObject(childinfo->startupCompletedEvent, 0) !=
+ 		WAIT_OBJECT_0)
+ 	{
+ 		/* Event not set, so we have an early death in the child */
+ 		write_stderr("process %lu died early", childinfo->procId);
+ 		exitcode = 1;
+ 	}
+ 
  	if (!PostQueuedCompletionStatus(win32ChildQueue, childinfo->procId, (ULONG_PTR) exitcode, NULL))
  		write_stderr("could not post child completion status\n");
  
***************
*** 4978,4983 **** pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
--- 5041,5047 ----
  	 * originating thread
  	 */
  	CloseHandle(childinfo->procHandle);
+ 	CloseHandle(childinfo->startupCompletedEvent);
  
  	/*
  	 * Free struct that was allocated before the call to
