bpo-38634: Allow non-apple build to cope with libedit (GH-16986)
The readline module now detects if Python is linked to libedit at runtime on all platforms. Previously, the check was only done on macOS. If Python is used as a library by a binary linking to libedit, the linker resolves the rl_initialize symbol required by the readline module against libedit instead of libreadline, which leads to a segfault. Take advantage of the existing supporting code to have readline module being compatible with both situations.
This commit is contained in:
parent
ac0e1c2694
commit
7105319ada
|
@ -0,0 +1,2 @@
|
|||
The :mod:`readline` module now detects if Python is linked to libedit at runtime
|
||||
on all platforms. Previously, the check was only done on macOS.
|
|
@ -45,14 +45,14 @@ extern char **completion_matches(char *, CPFunction *);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* It is possible to link the readline module to the readline
|
||||
* emulation library of editline/libedit.
|
||||
*
|
||||
* On OSX this emulation library is not 100% API compatible
|
||||
* with the "real" readline and cannot be detected at compile-time,
|
||||
* hence we use a runtime check to detect if we're using libedit
|
||||
* This emulation library is not 100% API compatible with the "real" readline
|
||||
* and cannot be detected at compile-time,
|
||||
* hence we use a runtime check to detect if the Python readlinke module is
|
||||
* linked to libedit.
|
||||
*
|
||||
* Currently there is one known API incompatibility:
|
||||
* - 'get_history' has a 1-based index with GNU readline, and a 0-based
|
||||
|
@ -64,7 +64,6 @@ static int using_libedit_emulation = 0;
|
|||
static const char libedit_version_tag[] = "EditLine wrapper";
|
||||
|
||||
static int libedit_history_start = 0;
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
|
||||
static void
|
||||
|
@ -693,7 +692,6 @@ get_history_item(PyObject *self, PyObject *args)
|
|||
|
||||
if (!PyArg_ParseTuple(args, "i:get_history_item", &idx))
|
||||
return NULL;
|
||||
#ifdef __APPLE__
|
||||
if (using_libedit_emulation) {
|
||||
/* Older versions of libedit's readline emulation
|
||||
* use 0-based indexes, while readline and newer
|
||||
|
@ -713,7 +711,6 @@ get_history_item(PyObject *self, PyObject *args)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
if ((hist_ent = history_get(idx)))
|
||||
return decode(hist_ent->line);
|
||||
else {
|
||||
|
@ -1081,7 +1078,6 @@ setup_readline(readlinestate *mod_state)
|
|||
/* The name must be defined before initialization */
|
||||
rl_readline_name = "python";
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* the libedit readline emulation resets key bindings etc
|
||||
* when calling rl_initialize. So call it upfront
|
||||
*/
|
||||
|
@ -1098,7 +1094,6 @@ setup_readline(readlinestate *mod_state)
|
|||
libedit_history_start = 1;
|
||||
}
|
||||
clear_history();
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
using_history();
|
||||
|
||||
|
@ -1127,9 +1122,7 @@ setup_readline(readlinestate *mod_state)
|
|||
mod_state->begidx = PyLong_FromLong(0L);
|
||||
mod_state->endidx = PyLong_FromLong(0L);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (!using_libedit_emulation)
|
||||
#endif
|
||||
{
|
||||
if (!isatty(STDOUT_FILENO)) {
|
||||
/* Issue #19884: stdout is not a terminal. Disable meta modifier
|
||||
|
@ -1149,11 +1142,9 @@ setup_readline(readlinestate *mod_state)
|
|||
* XXX: A bug in the readline-2.2 library causes a memory leak
|
||||
* inside this function. Nothing we can do about it.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
if (using_libedit_emulation)
|
||||
rl_read_init_file(NULL);
|
||||
else
|
||||
#endif /* __APPLE__ */
|
||||
rl_initialize();
|
||||
|
||||
RESTORE_LOCALE(saved_locale)
|
||||
|
@ -1283,12 +1274,10 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
|||
int length = _py_get_history_length();
|
||||
if (length > 0) {
|
||||
HIST_ENTRY *hist_ent;
|
||||
#ifdef __APPLE__
|
||||
if (using_libedit_emulation) {
|
||||
/* handle older 0-based or newer 1-based indexing */
|
||||
hist_ent = history_get(length + libedit_history_start - 1);
|
||||
} else
|
||||
#endif /* __APPLE__ */
|
||||
hist_ent = history_get(length);
|
||||
line = hist_ent ? hist_ent->line : "";
|
||||
} else
|
||||
|
@ -1316,10 +1305,8 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
|||
PyDoc_STRVAR(doc_module,
|
||||
"Importing this module enables command line editing using GNU readline.");
|
||||
|
||||
#ifdef __APPLE__
|
||||
PyDoc_STRVAR(doc_module_le,
|
||||
"Importing this module enables command line editing using libedit readline.");
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
static struct PyModuleDef readlinemodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
|
@ -1340,7 +1327,6 @@ PyInit_readline(void)
|
|||
PyObject *m;
|
||||
readlinestate *mod_state;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
|
||||
using_libedit_emulation = 1;
|
||||
}
|
||||
|
@ -1348,7 +1334,6 @@ PyInit_readline(void)
|
|||
if (using_libedit_emulation)
|
||||
readlinemodule.m_doc = doc_module_le;
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
m = PyModule_Create(&readlinemodule);
|
||||
|
||||
|
|
Loading…
Reference in New Issue