diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-06-14 16:49:03 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-06-14 16:49:03 +0000 |
| commit | f3164c020028de70e4cd991ccbd3d696c9060709 (patch) | |
| tree | 02b6ad16c4498a1d8609e9237b769e57eb1a6aaf /src/bin/psql/mainloop.c | |
| parent | ace93353eadf1316364bcb76f52952c413779083 (diff) | |
| download | postgresql-f3164c020028de70e4cd991ccbd3d696c9060709.tar.gz | |
Clean up psql's control-C handling to avoid longjmp'ing out of random
places --- that risks corrupting data structures, losing sync with the
backend, etc. We now longjmp only from calls to readline, fgets, and
fread, which we assume are coded to protect themselves against interrupts
at undesirable times. This requires adding explicit tests for
cancel_pressed in long-running loops, but on the whole it's far cleaner.
Martijn van Oosterhout and Tom Lane.
Diffstat (limited to 'src/bin/psql/mainloop.c')
| -rw-r--r-- | src/bin/psql/mainloop.c | 46 |
1 files changed, 18 insertions, 28 deletions
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index af297ae2a9..b7022281e5 100644 --- a/src/bin/psql/mainloop.c +++ b/src/bin/psql/mainloop.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.79 2006/06/11 23:06:00 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.80 2006/06/14 16:49:02 tgl Exp $ */ #include "postgres_fe.h" #include "mainloop.h" @@ -17,11 +17,6 @@ #include "psqlscan.h" #include "settings.h" -#ifndef WIN32 -#include <setjmp.h> -sigjmp_buf main_loop_jmp; -#endif - /* * Main processing loop for reading lines of input @@ -80,16 +75,14 @@ MainLoop(FILE *source) while (successResult == EXIT_SUCCESS) { /* - * Welcome code for Control-C + * Clean up after a previous Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* - * You get here if you stopped a script with Ctrl-C and a - * query cancel was issued. In that case we don't do the - * longjmp, so the query routine can finish nicely. + * You get here if you stopped a script with Ctrl-C. */ successResult = EXIT_USER; break; @@ -98,18 +91,24 @@ MainLoop(FILE *source) cancel_pressed = false; } -#ifndef WIN32 - if (sigsetjmp(main_loop_jmp, 1) != 0) + /* + * Establish longjmp destination for exiting from wait-for-input. + * We must re-do this each time through the loop for safety, since + * the jmpbuf might get changed during command execution. + */ + if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ - resetPQExpBuffer(query_buf); psql_scan_finish(scan_state); psql_scan_reset(scan_state); + resetPQExpBuffer(query_buf); + resetPQExpBuffer(history_buf); count_eof = 0; slashCmdStatus = PSQL_CMD_UNKNOWN; prompt_status = PROMPT_READY; + cancel_pressed = false; if (pset.cur_cmd_interactive) putc('\n', stdout); @@ -120,14 +119,6 @@ MainLoop(FILE *source) } } - /* - * establish the control-C handler only after main_loop_jmp is ready - */ - pqsignal(SIGINT, handle_sigint); /* control-C => cancel */ -#else /* WIN32 */ - setup_cancel_handler(); -#endif - fflush(stdout); /* @@ -360,14 +351,13 @@ MainLoop(FILE *source) } /* - * Reset SIGINT handler because main_loop_jmp will be invalid as soon as - * we exit this routine. If there is an outer MainLoop instance, it will - * re-enable ^C catching as soon as it gets back to the top of its loop - * and resets main_loop_jmp to point to itself. + * Let's just make real sure the SIGINT handler won't try to use + * sigint_interrupt_jmp after we exit this routine. If there is an outer + * MainLoop instance, it will reset sigint_interrupt_jmp to point to + * itself at the top of its loop, before any further interactive input + * happens. */ -#ifndef WIN32 - pqsignal(SIGINT, SIG_DFL); -#endif + sigint_interrupt_enabled = false; destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); |
