summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavan Deolasee2014-08-08 10:41:53 +0000
committerPavan Deolasee2014-09-01 14:20:31 +0000
commit46a7a2465810724b649983f3fa3da87123c1a27e (patch)
tree1e0bffe31fc36db06ccb565ee4ff1d521f0e40a9
parent507c656fddf33edb49786bd1d5f7c3aad81c7d8b (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.c17
-rw-r--r--contrib/pgxc_ctl/do_shell.c13
-rw-r--r--contrib/pgxc_ctl/do_shell.h5
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);