summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
diff options
context:
space:
mode:
authorserge-sans-paille <sguelton@redhat.com>2019-11-05 11:38:39 +0100
committerserge-sans-paille <sguelton@redhat.com>2019-11-05 11:39:19 +0100
commit9357b5d08497326a1895cab6c1d712bf12a34519 (patch)
tree4d9ce6e89c165af01b220532b12c0b84b84dc4d1 /lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
parent0e56b0f94bfc683c5a95e96784cfc9229a730bc8 (diff)
downloadbcm5719-llvm-9357b5d08497326a1895cab6c1d712bf12a34519.tar.gz
bcm5719-llvm-9357b5d08497326a1895cab6c1d712bf12a34519.zip
Revert and patch "[Python] Remove readline module"
Fix https://bugs.llvm.org/show_bug.cgi?id=43830 while avoiding polluting the global Python namespace. This both reverts r357277 to rebundle a version of Python's readline module based on libedit. However, this patch also provides two improvements over the previous implementation: 1. use PyMem_RawMalloc instead of PyMem_Malloc, as expected by PyOS_Readline (prevents to segfault upon exit of interactive session) 2. patch the readline module upon embedded interpreter loading, instead of patching it globally, which should prevent any side effect on other modules/packages 3. only activate the patched module if libedit is actually linked in lldb Differential Revision: https://reviews.llvm.org/D69793
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp')
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
new file mode 100644
index 00000000000..616522f9de9
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -0,0 +1,80 @@
+#include "PythonReadline.h"
+
+#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
+
+#include <stdio.h>
+
+#include <editline/readline.h>
+
+// Simple implementation of the Python readline module using libedit.
+// In the event that libedit is excluded from the build, this turns
+// back into a null implementation that blocks the module from pulling
+// in the GNU readline shared lib, which causes linkage confusion when
+// both readline and libedit's readline compatibility symbols collide.
+//
+// Currently it only installs a PyOS_ReadlineFunctionPointer, without
+// implementing any of the readline module methods. This is meant to
+// work around LLVM pr18841 to avoid seg faults in the stock Python
+// readline.so linked against GNU readline.
+//
+// Bug on the cpython side: https://bugs.python.org/issue38634
+
+PyDoc_STRVAR(moduleDocumentation,
+ "Simple readline module implementation based on libedit.");
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef readline_module = {
+ PyModuleDef_HEAD_INIT, // m_base
+ "lldb_editline", // m_name
+ moduleDocumentation, // m_doc
+ -1, // m_size
+ nullptr, // m_methods
+ nullptr, // m_reload
+ nullptr, // m_traverse
+ nullptr, // m_clear
+ nullptr, // m_free
+};
+#else
+static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
+#endif
+
+static char *
+#if PY_MAJOR_VERSION >= 3
+simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
+#else
+simple_readline(FILE *stdin, FILE *stdout, char *prompt)
+#endif
+{
+ rl_instream = stdin;
+ rl_outstream = stdout;
+ char *line = readline(prompt);
+ if (!line) {
+ char *ret = (char *)PyMem_RawMalloc(1);
+ if (ret != NULL)
+ *ret = '\0';
+ return ret;
+ }
+ if (*line)
+ add_history(line);
+ int n = strlen(line);
+ char *ret = (char *)PyMem_RawMalloc(n + 2);
+ if (ret) {
+ strncpy(ret, line, n);
+ free(line);
+ ret[n] = '\n';
+ ret[n + 1] = '\0';
+ }
+ return ret;
+}
+
+PyMODINIT_FUNC initlldb_readline(void) {
+ PyOS_ReadlineFunctionPointer = simple_readline;
+
+#if PY_MAJOR_VERSION >= 3
+ return PyModule_Create(&readline_module);
+#else
+ Py_InitModule4("lldb_readline", moduleMethods, moduleDocumentation,
+ static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
+#endif
+}
+#endif
OpenPOWER on IntegriCloud