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);