Skip to content

Commit 68669ef

Browse files
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. (cherry picked from commit 7105319) Co-authored-by: serge-sans-paille <[email protected]>
1 parent a75cad4 commit 68669ef

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 {
@@ -1080,7 +1077,6 @@ setup_readline(readlinestate *mod_state)
10801077
/* The name must be defined before initialization */
10811078
rl_readline_name = "python";
10821079

1083-
#ifdef __APPLE__
10841080
/* the libedit readline emulation resets key bindings etc
10851081
* when calling rl_initialize. So call it upfront
10861082
*/
@@ -1097,7 +1093,6 @@ setup_readline(readlinestate *mod_state)
10971093
libedit_history_start = 1;
10981094
}
10991095
clear_history();
1100-
#endif /* __APPLE__ */
11011096

11021097
using_history();
11031098

@@ -1126,9 +1121,7 @@ setup_readline(readlinestate *mod_state)
11261121
mod_state->begidx = PyLong_FromLong(0L);
11271122
mod_state->endidx = PyLong_FromLong(0L);
11281123

1129-
#ifdef __APPLE__
11301124
if (!using_libedit_emulation)
1131-
#endif
11321125
{
11331126
if (!isatty(STDOUT_FILENO)) {
11341127
/* Issue #19884: stdout is not a terminal. Disable meta modifier
@@ -1148,11 +1141,9 @@ setup_readline(readlinestate *mod_state)
11481141
* XXX: A bug in the readline-2.2 library causes a memory leak
11491142
* inside this function. Nothing we can do about it.
11501143
*/
1151-
#ifdef __APPLE__
11521144
if (using_libedit_emulation)
11531145
rl_read_init_file(NULL);
11541146
else
1155-
#endif /* __APPLE__ */
11561147
rl_initialize();
11571148

11581149
RESTORE_LOCALE(saved_locale)
@@ -1281,12 +1272,10 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
12811272
int length = _py_get_history_length();
12821273
if (length > 0) {
12831274
HIST_ENTRY *hist_ent;
1284-
#ifdef __APPLE__
12851275
if (using_libedit_emulation) {
12861276
/* handle older 0-based or newer 1-based indexing */
12871277
hist_ent = history_get(length + libedit_history_start - 1);
12881278
} else
1289-
#endif /* __APPLE__ */
12901279
hist_ent = history_get(length);
12911280
line = hist_ent ? hist_ent->line : "";
12921281
} else
@@ -1314,10 +1303,8 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
13141303
PyDoc_STRVAR(doc_module,
13151304
"Importing this module enables command line editing using GNU readline.");
13161305

1317-
#ifdef __APPLE__
13181306
PyDoc_STRVAR(doc_module_le,
13191307
"Importing this module enables command line editing using libedit readline.");
1320-
#endif /* __APPLE__ */
13211308

13221309
static struct PyModuleDef readlinemodule = {
13231310
PyModuleDef_HEAD_INIT,
@@ -1338,15 +1325,13 @@ PyInit_readline(void)
13381325
PyObject *m;
13391326
readlinestate *mod_state;
13401327

1341-
#ifdef __APPLE__
13421328
if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
13431329
using_libedit_emulation = 1;
13441330
}
13451331

13461332
if (using_libedit_emulation)
13471333
readlinemodule.m_doc = doc_module_le;
13481334

1349-
#endif /* __APPLE__ */
13501335

13511336
m = PyModule_Create(&readlinemodule);
13521337

0 commit comments

Comments
 (0)