*** src/backend/port/win32/signal.c.orig	Fri Oct 21 17:43:45 2005
--- src/backend/port/win32/signal.c	Sun Oct 23 15:35:23 2005
***************
*** 90,105 ****
  }
  
  /*
-  * Support routine for CHECK_FOR_INTERRUPTS() macro
-  */
- void
- pgwin32_check_queued_signals(void)
- {
- 	if (WaitForSingleObjectEx(pgwin32_signal_event, 0, TRUE) == WAIT_OBJECT_0)
- 		pgwin32_dispatch_queued_signals();
- }
- 
- /*
   * Dispatch all signals currently queued and not blocked
   * Blocked signals are ignored, and will be fired at the time of
   * the sigsetmask() call.
--- 90,95 ----
*** src/backend/port/win32/socket.c.orig	Fri Oct 14 22:59:56 2005
--- src/backend/port/win32/socket.c	Sun Oct 23 15:37:21 2005
***************
*** 93,99 ****
  static int
  pgwin32_poll_signals(void)
  {
! 	if (WaitForSingleObjectEx(pgwin32_signal_event, 0, TRUE) == WAIT_OBJECT_0)
  	{
  		pgwin32_dispatch_queued_signals();
  		errno = EINTR;
--- 93,99 ----
  static int
  pgwin32_poll_signals(void)
  {
! 	if (UNBLOCKED_SIGNAL_QUEUE())
  	{
  		pgwin32_dispatch_queued_signals();
  		errno = EINTR;
*** src/backend/port/win32/timer.c.orig	Fri Dec 31 17:00:37 2004
--- src/backend/port/win32/timer.c	Sun Oct 23 15:46:45 2005
***************
*** 3,8 ****
--- 3,13 ----
   * timer.c
   *	  Microsoft Windows Win32 Timer Implementation
   *
+  *    Limitations of this implementation:
+  *
+  *    - Does not support interval timer (value->it_interval)
+  *    - Only supports ITIMER_REAL
+  *
   * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
   *
   * IDENTIFICATION
***************
*** 16,71 ****
  #include "libpq/pqsignal.h"
  
  
! static HANDLE timerHandle = INVALID_HANDLE_VALUE;
  
! static VOID CALLBACK
! timer_completion(LPVOID arg, DWORD timeLow, DWORD timeHigh)
  {
! 	pg_queue_signal(SIGALRM);
! }
  
  
  /*
!  * Limitations of this implementation:
!  *
!  * - Does not support setting ovalue
!  * - Does not support interval timer (value->it_interval)
!  * - Only supports ITIMER_REAL
   */
  int
  setitimer(int which, const struct itimerval * value, struct itimerval * ovalue)
  {
- 	LARGE_INTEGER dueTime;
- 
- 	Assert(ovalue == NULL);
  	Assert(value != NULL);
  	Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
  	Assert(which == ITIMER_REAL);
  
! 	if (timerHandle == INVALID_HANDLE_VALUE)
  	{
! 		/* First call in this backend, create new timer object */
! 		timerHandle = CreateWaitableTimer(NULL, TRUE, NULL);
! 		if (timerHandle == NULL)
  			ereport(FATAL,
! 					(errmsg_internal("failed to create waitable timer: %i", (int) GetLastError())));
! 	}
  
! 	if (value->it_value.tv_sec == 0 &&
! 		value->it_value.tv_usec == 0)
! 	{
! 		/* Turn timer off */
! 		CancelWaitableTimer(timerHandle);
! 		return 0;
! 	}
  
! 	/* Negative time to SetWaitableTimer means relative time */
! 	dueTime.QuadPart = -(value->it_value.tv_usec * 10 + value->it_value.tv_sec * 10000000L);
  
! 	/* Turn timer on, or change timer */
! 	if (!SetWaitableTimer(timerHandle, &dueTime, 0, timer_completion, NULL, FALSE))
! 		ereport(FATAL,
! 				(errmsg_internal("failed to set waitable timer: %i", (int) GetLastError())));
  
  	return 0;
  }
--- 21,118 ----
  #include "libpq/pqsignal.h"
  
  
! /* Communication area for inter-thread communication */
! typedef struct timerCA {
! 	struct itimerval value;
! 	HANDLE event;
! 	CRITICAL_SECTION crit_sec;
! } timerCA;
! 
! static timerCA timerCommArea;
! static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE;
! 
  
! /* Timer management thread */
! static DWORD WINAPI
! pg_timer_thread(LPVOID param)
  {
! 	DWORD waittime;
! 
! 	Assert(param == NULL);
  
+ 	waittime = INFINITE;
+ 
+ 	for (;;)
+ 	{
+ 		int r;
+ 
+ 		r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE);
+ 		if (r == WAIT_OBJECT_0)
+ 		{
+ 			/* Event signalled from main thread, change the timer */
+ 			EnterCriticalSection(&timerCommArea.crit_sec);
+ 			if (timerCommArea.value.it_value.tv_sec == 0 &&
+ 				timerCommArea.value.it_value.tv_usec == 0)
+ 				waittime = INFINITE; /* Cancel the interrupt */
+ 			else
+ 				waittime = timerCommArea.value.it_value.tv_usec / 10 + timerCommArea.value.it_value.tv_sec * 1000;
+ 			ResetEvent(timerCommArea.event);
+ 			LeaveCriticalSection(&timerCommArea.crit_sec);
+ 		}
+ 		else if (r == WAIT_TIMEOUT)
+ 		{
+ 			/* Timeout expired, signal SIGALRM and turn it off */
+ 			pg_queue_signal(SIGALRM);
+ 			waittime = INFINITE;
+ 		}
+ 		else
+ 		{
+ 			/* Should never happen */
+ 			Assert(false);
+ 		}
+ 	}
+ 
+ 	return 0;
+ }
  
  /*
!  * Win32 setitimer emulation by creating a persistent thread
!  * to handle the timer setting and notification upon timeout.
   */
  int
  setitimer(int which, const struct itimerval * value, struct itimerval * ovalue)
  {
  	Assert(value != NULL);
  	Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
  	Assert(which == ITIMER_REAL);
  
! 	if (timerThreadHandle == INVALID_HANDLE_VALUE)
  	{
! 		/* First call in this backend, create event and the timer thread */
! 		timerCommArea.event = CreateEvent(NULL, TRUE, FALSE, NULL);
! 		if (timerCommArea.event == NULL)
  			ereport(FATAL,
! 					(errmsg_internal("failed to create timer event: %d",
! 									 (int) GetLastError())));
  
! 		MemSet(&timerCommArea.value, 0, sizeof(struct itimerval));
! 
! 		InitializeCriticalSection(&timerCommArea.crit_sec);
  
! 		timerThreadHandle = CreateThread(NULL, 0, pg_timer_thread, NULL, 0, NULL);
! 		if (timerThreadHandle == INVALID_HANDLE_VALUE)
! 			ereport(FATAL,
! 					(errmsg_internal("failed to create timer thread: %d",
! 									 (int) GetLastError())));
! 	}
  
! 	/* Request the timer thread to change settings */
! 	EnterCriticalSection(&timerCommArea.crit_sec);
! 	if (ovalue)
! 		*ovalue = timerCommArea.value;
! 	timerCommArea.value = *value;
! 	LeaveCriticalSection(&timerCommArea.crit_sec);
! 	SetEvent(timerCommArea.event);
  
  	return 0;
  }
*** src/include/miscadmin.h.orig	Sat Oct 22 13:09:48 2005
--- src/include/miscadmin.h	Sun Oct 23 15:34:40 2005
***************
*** 88,94 ****
  
  #define CHECK_FOR_INTERRUPTS() \
  do { \
! 	pgwin32_check_queued_signals(); \
  	if (InterruptPending) \
  		ProcessInterrupts(); \
  } while(0)
--- 88,95 ----
  
  #define CHECK_FOR_INTERRUPTS() \
  do { \
! 	if (UNBLOCKED_SIGNAL_QUEUE()) \
! 		pgwin32_dispatch_queued_signals(); \
  	if (InterruptPending) \
  		ProcessInterrupts(); \
  } while(0)
*** src/include/port/win32.h.orig	Fri Oct 21 17:43:46 2005
--- src/include/port/win32.h	Sun Oct 23 15:34:18 2005
***************
*** 224,230 ****
  
  void		pgwin32_signal_initialize(void);
  HANDLE		pgwin32_create_signal_listener(pid_t pid);
- void		pgwin32_check_queued_signals(void);
  void		pgwin32_dispatch_queued_signals(void);
  void		pg_queue_signal(int signum);
  
--- 224,229 ----
