diff options
author | Pavan Deolasee | 2014-08-08 10:41:53 +0000 |
---|---|---|
committer | Pavan Deolasee | 2014-09-01 14:20:31 +0000 |
commit | 46a7a2465810724b649983f3fa3da87123c1a27e (patch) | |
tree | 1e0bffe31fc36db06ccb565ee4ff1d521f0e40a9 | |
parent | 507c656fddf33edb49786bd1d5f7c3aad81c7d8b (diff) |
Handle SIGINT while processing commands.
With this the pgxc_ctl utility will come back to the command prompt if
interrupted in between. Unfortunately, this works only when pgxc_ctl forks a
new process to execute a command. At many places, it uses system() function to
execute a command. By specifications, when system() function is called, process
waits for the command to complete ignoring SIGINT and SIGQUIT. So we must find
some other way to handle those paths.
-rw-r--r-- | contrib/pgxc_ctl/do_command.c | 17 | ||||
-rw-r--r-- | contrib/pgxc_ctl/do_shell.c | 13 | ||||
-rw-r--r-- | contrib/pgxc_ctl/do_shell.h | 5 |
3 files changed, 35 insertions, 0 deletions
diff --git a/contrib/pgxc_ctl/do_command.c b/contrib/pgxc_ctl/do_command.c index 3c6791ca7b..8a7cf0c4dc 100644 --- a/contrib/pgxc_ctl/do_command.c +++ b/contrib/pgxc_ctl/do_command.c @@ -2226,6 +2226,19 @@ void do_command(FILE *inf, FILE *outf) read_history(histfile); } + /* + * Set the long jump path so that we can come out straight here in case of + * an error. There is not much to reinitialize except may be freeing up the + * wkline buffer and resetting the long jump buffer pointer. But if + * anything else needs to reset, that should happen in the following block + */ + if (setjmp(dcJmpBufMainLoop) != 0) + { + whereToJumpMainLoop = NULL; + if (wkline) + freeAndReset(wkline); + } + for (;;) { if (wkline) @@ -2251,7 +2264,11 @@ void do_command(FILE *inf, FILE *outf) } trimNl(buf); writeLogOnly("PGXC %s\n", buf); + + whereToJumpMainLoop = &dcJmpBufMainLoop; rc = do_singleLine(buf, wkline); + whereToJumpMainLoop = NULL; + freeAndReset(wkline); if (rc) /* "q" command was found */ { diff --git a/contrib/pgxc_ctl/do_shell.c b/contrib/pgxc_ctl/do_shell.c index 65c6fa68f8..20c35ac96b 100644 --- a/contrib/pgxc_ctl/do_shell.c +++ b/contrib/pgxc_ctl/do_shell.c @@ -60,6 +60,8 @@ static void prepareStdout(cmdList_t *cmdList); */ jmp_buf *whereToJumpDoShell = NULL; jmp_buf dcJmpBufDoShell; +jmp_buf *whereToJumpMainLoop = NULL; +jmp_buf dcJmpBufMainLoop; pqsigfunc old_HandlerDoShell = NULL; void do_shell_SigHandler(int signum); @@ -443,6 +445,11 @@ int doCmdList(cmdList_t *cmds) } } elog(NOTICE, "%s:%d Finish by interrupt\n", __FUNCTION__, __LINE__); + if (whereToJumpMainLoop) + { + elog(NOTICE, "Control reaches to the mainloop\n"); + longjmp(*whereToJumpMainLoop, 1); + } return 2; } /* @@ -501,6 +508,12 @@ int doCmdList(cmdList_t *cmds) freeAndReset(cmds->cmds[jj]->remoteStdout); } elog(NOTICE, "%s:%d Finish by interrupt\n", __FUNCTION__, __LINE__); + + if (whereToJumpMainLoop) + { + elog(NOTICE, "Control reaches to the mainloop\n"); + longjmp(*whereToJumpMainLoop, 1); + } return(2); } signal(SIGINT, old_HandlerDoShell); diff --git a/contrib/pgxc_ctl/do_shell.h b/contrib/pgxc_ctl/do_shell.h index a84e8a74be..88d72d3060 100644 --- a/contrib/pgxc_ctl/do_shell.h +++ b/contrib/pgxc_ctl/do_shell.h @@ -11,6 +11,11 @@ #ifndef DO_SHELL_H #define DO_SHELL_H +#include <setjmp.h> + +extern jmp_buf *whereToJumpMainLoop; +extern jmp_buf dcJmpBufMainLoop; + extern void dcSigHandler(int signum); typedef enum FileType { STDIN, STDOUT, STDERR, GENERAL } FileType; typedef void (*pqsigfunc) (int); |