Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/common.c,v
retrieving revision 1.92
diff -c -r1.92 common.c
*** common.c	10 Oct 2004 23:37:40 -0000	1.92
--- common.c	30 Oct 2004 12:51:52 -0000
***************
*** 223,241 ****
   *
   * Before we start a query, we enable a SIGINT signal catcher that sends a
   * cancel request to the backend. Note that sending the cancel directly from
!  * the signal handler is safe because PQrequestCancel() is written to make it
   * so. We use write() to print to stdout because it's better to use simple
   * facilities in a signal handler.
   */
! static PGconn *volatile cancelConn = NULL;
  
  volatile bool cancel_pressed = false;
  
  
- #ifndef WIN32
  
  #define write_stderr(String) write(fileno(stderr), String, strlen(String))
  
  void
  handle_sigint(SIGNAL_ARGS)
  {
--- 223,249 ----
   *
   * Before we start a query, we enable a SIGINT signal catcher that sends a
   * cancel request to the backend. Note that sending the cancel directly from
!  * the signal handler is safe because PQcancel() is written to make it
   * so. We use write() to print to stdout because it's better to use simple
   * facilities in a signal handler.
+  *
+  * On win32, the signal cancelling happens on a separate thread, because
+  * that's how SetConsoleCtrlHandler works. The PQcancel function is safe 
+  * or this, unlike PQrequestCancel. However, a CRITICAL_SECTION is required
+  * to protect the PGcancel structure during all usage.
   */
! static PGcancel *cancelConn = NULL;
! #ifdef WIN32
! static CRITICAL_SECTION cancelConnLock;
! #endif
  
  volatile bool cancel_pressed = false;
  
  
  
  #define write_stderr(String) write(fileno(stderr), String, strlen(String))
  
+ #ifndef WIN32
  void
  handle_sigint(SIGNAL_ARGS)
  {
***************
*** 250,265 ****
  
  	cancel_pressed = true;
  
! 	if (PQrequestCancel(cancelConn))
  		write_stderr("Cancel request sent\n");
  	else
  	{
  		write_stderr("Could not send cancel request: ");
! 		write_stderr(PQerrorMessage(cancelConn));
  	}
  	errno = save_errno;			/* just in case the write changed it */
  }
! #endif   /* not WIN32 */
  
  
  
--- 258,312 ----
  
  	cancel_pressed = true;
  
! 	if (PQcancel(cancelConn))
  		write_stderr("Cancel request sent\n");
  	else
  	{
  		write_stderr("Could not send cancel request: ");
! 		write_stderr(PQgetCancelError(cancelConn));
  	}
  	errno = save_errno;			/* just in case the write changed it */
  }
! #else /* WIN32 */
! 
! static BOOL WINAPI consoleHandler(DWORD dwCtrlType)
! {
! 	if (dwCtrlType == CTRL_C_EVENT ||
! 		dwCtrlType == CTRL_BREAK_EVENT)
! 	{
! 		if (prompt_state)
! 			return;
! 
! 		/* Perform query cancel */
! 		EnterCriticalSection(&cancelConnLock);
! 		if (cancelConn != NULL)
! 		{
! 			cancel_pressed = true;
! 
! 			if (PQcancel(cancelConn))
! 				write_stderr("Cancel request sent\n");
! 			else
! 			{
! 				write_stderr("Could not send cancel request: ");
! 				write_stderr(PQgetCancelError(cancelConn));
! 			}
! 		}
! 		LeaveCriticalSection(&cancelConnLock);
! 		
! 		return TRUE;
! 	}
! 	else
! 		/* Return FALSE for any signals not being handled */
! 		return FALSE;
! }
! 
! void
! setup_cancel_handler(void)
! {
! 	InitializeCriticalSection(&cancelConnLock);
! 	SetConsoleCtrlHandler(consoleHandler, TRUE);
! }
! #endif
  
  
  
***************
*** 327,346 ****
  static void
  SetCancelConn(void)
  {
! 	cancelConn = pset.db;
  }
  
  
  /*
   * ResetCancelConn
   *
!  * Set cancelConn to NULL.	I don't know what this means exactly, but it saves
!  * having to export the variable.
   */
  void
  ResetCancelConn(void)
  {
  	cancelConn = NULL;
  }
  
  
--- 374,411 ----
  static void
  SetCancelConn(void)
  {
! #ifdef WIN32
! 	EnterCriticalSection(&cancelConnLock);
! #endif
! 	/* Free the old one if we have one */
! 	if (cancelConn != NULL)
! 		PQfreeCancel(cancelConn);
! 
! 	cancelConn = PQgetCancel(pset.db);
! #ifdef WIN32
! 	LeaveCriticalSection(&cancelConnLock);
! #endif
  }
  
  
  /*
   * ResetCancelConn
   *
!  * Free the current cancel connection, if any, and set to NULL.
   */
  void
  ResetCancelConn(void)
  {
+ #ifdef WIN32
+ 	EnterCriticalSection(&cancelConnLock);
+ #endif
+ 	if (cancelConn)
+ 		PQfreeCancel(cancelConn);
+ 
  	cancelConn = NULL;
+ #ifdef WIN32
+ 	LeaveCriticalSection(&cancelConnLock);
+ #endif
  }
  
  
Index: common.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/common.h,v
retrieving revision 1.39
diff -c -r1.39 common.h
*** common.h	29 Aug 2004 04:13:02 -0000	1.39
--- common.h	30 Oct 2004 12:34:40 -0000
***************
*** 48,54 ****
  
  #ifndef WIN32
  extern void handle_sigint(SIGNAL_ARGS);
! #endif   /* not WIN32 */
  
  extern PGresult *PSQLexec(const char *query, bool start_xact);
  
--- 48,56 ----
  
  #ifndef WIN32
  extern void handle_sigint(SIGNAL_ARGS);
! #else /* WIN32 */
! extern void setup_cancel_handler(void);
! #endif
  
  extern PGresult *PSQLexec(const char *query, bool start_xact);
  
Index: mainloop.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/mainloop.c,v
retrieving revision 1.64
diff -c -r1.64 mainloop.c
*** mainloop.c	29 Aug 2004 05:06:54 -0000	1.64
--- mainloop.c	30 Oct 2004 12:31:57 -0000
***************
*** 121,127 ****
  		 * ready
  		 */
  		pqsignal(SIGINT, handle_sigint);		/* control-C => cancel */
! #endif   /* not WIN32 */
  
  		fflush(stdout);
  
--- 121,129 ----
  		 * ready
  		 */
  		pqsignal(SIGINT, handle_sigint);		/* control-C => cancel */
! #else /* WIN32 */
! 		setup_cancel_handler(); /* in common.c */
! #endif
  
  		fflush(stdout);
  
