summaryrefslogtreecommitdiffstats
path: root/Modules/readline.c
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2004-07-07 17:44:12 (GMT)
committerMichael W. Hudson <mwh@python.net>2004-07-07 17:44:12 (GMT)
commit30ea2f223f5c0a85a13bd893063555a9f587cd6d (patch)
treed9ad0b824eb899d1163043d982dd7d961b11a263 /Modules/readline.c
parente3c330b42a5dbc64a254354e906885134a852949 (diff)
downloadcpython-30ea2f223f5c0a85a13bd893063555a9f587cd6d.zip
cpython-30ea2f223f5c0a85a13bd893063555a9f587cd6d.tar.gz
cpython-30ea2f223f5c0a85a13bd893063555a9f587cd6d.tar.bz2
This closes patch:
[ 960406 ] unblock signals in threads although the changes do not correspond exactly to any patch attached to that report. Non-main threads no longer have all signals masked. A different interface to readline is used. The handling of signals inside calls to PyOS_Readline is now rather different. These changes are all a bit scary! Review and cross-platform testing much appreciated.
Diffstat (limited to 'Modules/readline.c')
-rw-r--r--Modules/readline.c97
1 files changed, 89 insertions, 8 deletions
diff --git a/Modules/readline.c b/Modules/readline.c
index 37baf87..8285d33 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -656,6 +656,66 @@ setup_readline(void)
#endif
}
+/* Wrapper around GNU readline that handles signals differently. */
+
+
+#if defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT)
+
+static char *completed_input_string;
+static void
+rlhandler(char *text)
+{
+ completed_input_string = text;
+ rl_callback_handler_remove();
+}
+
+extern PyThreadState* _PyOS_ReadlineTState;
+
+static char *
+readline_until_enter_or_signal(char *prompt, int *signal)
+{
+ char * not_done_reading = "";
+ fd_set selectset;
+
+ *signal = 0;
+#ifdef HAVE_RL_CATCH_SIGNAL
+ rl_catch_signals = 0;
+#endif
+
+ rl_callback_handler_install (prompt, rlhandler);
+ FD_ZERO(&selectset);
+ FD_SET(fileno(rl_instream), &selectset);
+
+ completed_input_string = not_done_reading;
+
+ while(completed_input_string == not_done_reading) {
+ int has_input;
+
+ has_input = select(fileno(rl_instream) + 1, &selectset,
+ NULL, NULL, NULL);
+ if(has_input > 0) {
+ rl_callback_read_char();
+ }
+ else if (errno == EINTR) {
+ int s;
+ PyEval_RestoreThread(_PyOS_ReadlineTState);
+ s = PyErr_CheckSignals();
+ PyThreadState_Swap(NULL);
+ if (s < 0) {
+ rl_free_line_state();
+ rl_cleanup_after_signal();
+ rl_callback_handler_remove();
+ *signal = 1;
+ completed_input_string = NULL;
+ }
+ }
+ }
+
+ return completed_input_string;
+}
+
+
+#else
/* Interrupt handler */
@@ -669,14 +729,13 @@ onintr(int sig)
}
-/* Wrapper around GNU readline that handles signals differently. */
-
static char *
-call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
+readline_until_enter_or_signal(char *prompt, int *signal)
{
- size_t n;
- char *p, *q;
PyOS_sighandler_t old_inthandler;
+ char *p;
+
+ *signal = 0;
old_inthandler = PyOS_setsig(SIGINT, onintr);
if (setjmp(jbuf)) {
@@ -685,8 +744,24 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
sigrelse(SIGINT);
#endif
PyOS_setsig(SIGINT, old_inthandler);
+ *signal = 1;
return NULL;
}
+ p = readline(prompt);
+ PyOS_setsig(SIGINT, old_inthandler);
+
+ return p;
+}
+#endif /*defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT) */
+
+
+static char *
+call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
+{
+ size_t n;
+ char *p, *q;
+ int signal;
+
rl_event_hook = PyOS_InputHook;
if (sys_stdin != rl_instream || sys_stdout != rl_outstream) {
@@ -697,16 +772,22 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
#endif
}
- p = readline(prompt);
- PyOS_setsig(SIGINT, old_inthandler);
+ p = readline_until_enter_or_signal(prompt, &signal);
+
+ /* we got an interrupt signal */
+ if(signal) {
+ return NULL;
+ }
- /* We must return a buffer allocated with PyMem_Malloc. */
+ /* We got an EOF, return a empty string. */
if (p == NULL) {
p = PyMem_Malloc(1);
if (p != NULL)
*p = '\0';
return p;
}
+
+ /* we have a valid line */
n = strlen(p);
if (n > 0) {
char *line;