Skip to content

Commit 7105319

Browse files
serge-sans-paillevstinner
authored andcommitted
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.
1 parent ac0e1c2 commit 7105319

File tree

2 files changed

+6
-19
lines changed

2 files changed

+6
-19
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :mod:`readline` module now detects if Python is linked to libedit at runtime
2+
on all platforms. Previously, the check was only done on macOS.

Modules/readline.c

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ extern char **completion_matches(char *, CPFunction *);
4545
#endif
4646
#endif
4747

48-
#ifdef __APPLE__
4948
/*
5049
* It is possible to link the readline module to the readline
5150
* emulation library of editline/libedit.
5251
*
53-
* On OSX this emulation library is not 100% API compatible
54-
* with the "real" readline and cannot be detected at compile-time,
55-
* hence we use a runtime check to detect if we're using libedit
52+
* This emulation library is not 100% API compatible with the "real" readline
53+
* and cannot be detected at compile-time,
54+
* hence we use a runtime check to detect if the Python readlinke module is
55+
* linked to libedit.
5656
*
5757
* Currently there is one known API incompatibility:
5858
* - 'get_history' has a 1-based index with GNU readline, and a 0-based
@@ -64,7 +64,6 @@ static int using_libedit_emulation = 0;
6464
static const char libedit_version_tag[] = "EditLine wrapper";
6565

6666
static int libedit_history_start = 0;
67-
#endif /* __APPLE__ */
6867

6968
#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
7069
static void
@@ -693,7 +692,6 @@ get_history_item(PyObject *self, PyObject *args)
693692

694693
if (!PyArg_ParseTuple(args, "i:get_history_item", &idx))
695694
return NULL;
696-
#ifdef __APPLE__
697695
if (using_libedit_emulation) {
698696
/* Older versions of libedit's readline emulation
699697
* use 0-based indexes, while readline and newer
@@ -713,7 +711,6 @@ get_history_item(PyObject *self, PyObject *args)
713711
Py_RETURN_NONE;
714712
}
715713
}
716-
#endif /* __APPLE__ */
717714
if ((hist_ent = history_get(idx)))
718715
return decode(hist_ent->line);
719716
else {
@@ -1081,7 +1078,6 @@ setup_readline(readlinestate *mod_state)
10811078
/* The name must be defined before initialization */
10821079
rl_readline_name = "python";
10831080

1084-
#ifdef __APPLE__
10851081
/* the libedit readline emulation resets key bindings etc
10861082
* when calling rl_initialize. So call it upfront
10871083
*/
@@ -1098,7 +1094,6 @@ setup_readline(readlinestate *mod_state)
10981094
libedit_history_start = 1;
10991095
}
11001096
clear_history();
1101-
#endif /* __APPLE__ */
11021097

11031098
using_history();
11041099

@@ -1127,9 +1122,7 @@ setup_readline(readlinestate *mod_state)
11271122
mod_state->begidx = PyLong_FromLong(0L);
11281123
mod_state->endidx = PyLong_FromLong(0L);
11291124

1130-
#ifdef __APPLE__
11311125
if (!using_libedit_emulation)
1132-
#endif
11331126
{
11341127
if (!isatty(STDOUT_FILENO)) {
11351128
/* Issue #19884: stdout is not a terminal. Disable meta modifier
@@ -1149,11 +1142,9 @@ setup_readline(readlinestate *mod_state)
11491142
* XXX: A bug in the readline-2.2 library causes a memory leak
11501143
* inside this function. Nothing we can do about it.
11511144
*/
1152-
#ifdef __APPLE__
11531145
if (using_libedit_emulation)
11541146
rl_read_init_file(NULL);
11551147
else
1156-
#endif /* __APPLE__ */
11571148
rl_initialize();
11581149

11591150
RESTORE_LOCALE(saved_locale)
@@ -1283,12 +1274,10 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
12831274
int length = _py_get_history_length();
12841275
if (length > 0) {
12851276
HIST_ENTRY *hist_ent;
1286-
#ifdef __APPLE__
12871277
if (using_libedit_emulation) {
12881278
/* handle older 0-based or newer 1-based indexing */
12891279
hist_ent = history_get(length + libedit_history_start - 1);
12901280
} else
1291-
#endif /* __APPLE__ */
12921281
hist_ent = history_get(length);
12931282
line = hist_ent ? hist_ent->line : "";
12941283
} else
@@ -1316,10 +1305,8 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
13161305
PyDoc_STRVAR(doc_module,
13171306
"Importing this module enables command line editing using GNU readline.");
13181307

1319-
#ifdef __APPLE__
13201308
PyDoc_STRVAR(doc_module_le,
13211309
"Importing this module enables command line editing using libedit readline.");
1322-
#endif /* __APPLE__ */
13231310

13241311
static struct PyModuleDef readlinemodule = {
13251312
PyModuleDef_HEAD_INIT,
@@ -1340,15 +1327,13 @@ PyInit_readline(void)
13401327
PyObject *m;
13411328
readlinestate *mod_state;
13421329

1343-
#ifdef __APPLE__
13441330
if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
13451331
using_libedit_emulation = 1;
13461332
}
13471333

13481334
if (using_libedit_emulation)
13491335
readlinemodule.m_doc = doc_module_le;
13501336

1351-
#endif /* __APPLE__ */
13521337

13531338
m = PyModule_Create(&readlinemodule);
13541339

0 commit comments

Comments
 (0)