Comments (10)
(I reported the initial Debian bug against rlwrap
)
It appears to be a readline
issue, as I get the same behavior with Python (2.x or 3.x) which uses readline
under the hood:
$ python
…
>>> import cmd
>>> cmd.Cmd().cmdloop()
(Cmd) # do C-x ( <NL> <NL> C-x ) C-x e and it segfaults
Mike Miller (at Debian) reduced the test case to simply having more than one <NL>
in it.
Note that readline
appears to handle the multi-line macro in bash
just fine:
bash$ # just typed C-x ( before this line
bash$ # and here's a second line
bash$ # typed C-x ) before this line, and about to type C-x e on the next line
bash$ # just typed C-x ( before this line
bash$ # and here's a second line
Note that it plays back the two recorded lines just fine.
from rlwrap.
Thanks a million! Closing (for now, but it might turn out that python
and rlwrap
are both unwittingly violating some constraint on the use of the rl*()
functions)
from rlwrap.
I'm unfamiliar with the readline
libraries, so is there an upstream against which this should be reported?
from rlwrap.
Before reporting this to the Bug-readline list, I'll have a closer look. I always give an MWE when reporting a bug, and until now, I haven't been able to find it, as the simplest test program that uses the "callback interface" (as rlwrap
does) works just fine on the same input that crashes rlwrap
(and , apparently, also python
s cmdloop
)
So, the following program works correctly:
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
void line_handler(char *line) { /* This function (callback) gets called by readline
whenever rl_callback_read_char sees an ENTER */
printf("You typed: '%s'\n", line);
}
int main() {
rl_callback_handler_install("Type anything: ", &line_handler);
while (1)
rl_callback_read_char();
}
For now, I'm reopening (until I have an MWE)
from rlwrap.
Confirmed here, your simple example program works for me, but both rlwrap and python segfault, and both are using the callback interface.
I have not figured out the sequence of events yet, but the segfault occurs when the callback handler function has been reset to NULL
during the call to rl_callback_read_char()
. This seems related to the way that the callback function is installed and removed during execution.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff79be2ab in rl_callback_read_char () at ../callback.c:238
#2 0x000000000040553a in main_loop () at main.c:552
#3 0x00000000004035de in main (argc=2, argv=0x7fffffffde28) at main.c:181
(gdb) up
#1 0x00007ffff79be2ab in rl_callback_read_char () at ../callback.c:238
238 (*rl_linefunc) (line);
(gdb) list
233 (*rl_deprep_term_function) ();
234 #if defined (HANDLE_SIGNALS)
235 rl_clear_signals ();
236 #endif
237 in_handler = 0;
238 (*rl_linefunc) (line);
239
240 /* If the user did not clear out the line, do it for him. */
241 if (rl_line_buffer[0])
242 _rl_init_line_state ();
(gdb) p rl_linefunc
$1 = (rl_vcpfunc_t *) 0x0
from rlwrap.
rlwrap
assumes (incorrectly, as it turns out only now) that the line_handler()
will never be called twice in succession without an intervening keypress. Hence the line_handler
(or rather, its author...) thinks it can get away with calling rl_callback_handler_remove()
because the callback handler will be re-installed in the main loop as soon as a keypress is seen.
This explains why we need a macro with two newlines to cause a crash: the first line is handled just fine by line_handler()
, which removes itself, so that the second line is called with a NULL handler, which is clearly visible in Mike's stack trace:
(gdb) bt
#0 0x0000000000000000 in ?? ()
rlwrap
needs all this trickery with saving and restoring readline
s state to maintain transparency.
I cannot think of a good reason why Python's cmd.Cmd().cmdloop()
should have the same problems, but it is possible that the same wrong assumption is creating havoc there as well (edit: yes it is, cf issue 25259)
I'll have to think of a way to move the rl_callback_handler_remove()
call out of the line_handler
, to somewhere in the main loop, or else find some other way to reset the terminal to its pristine state. To be continued....
from rlwrap.
I created a branch persistent_linehandler in which I moved the cleanup code at the end of line_handler()
to inside the main loop itself. Quick and dirty, but it seems to do the job. This will need some testing!
from rlwrap.
Not removing the line_handler()
will make readline
reprint the prompt, and it will do so without checking for wrapped-around (very long) prompts, as rlwrap
does. Not good.
New attempt: now, the linehandler checks rl_readline_state
to see whether a macro is being played back. In that case the rl_callback_handler_remove()
call is skipped:
if(!RL_ISSTATE(RL_STATE_MACROINPUT))
rl_callback_handler_remove();
This is much less intrusive, and works pretty well until now. This is probably also a good and easy fix for the Python folks!
from rlwrap.
OK, this works, and is minimally intrusive. Merging and closing.
from rlwrap.
My comments above are muddle-headed, as it is not the line handler, but the callback handler that is being removed. That should be harmless, but apparently isn't (calling rl_callback_handler_remove()
twice in succession doesn't seem to be harmful)
from rlwrap.
Related Issues (20)
- Python filter can't be loaded HOT 4
- build failed: possibly undefined macro: AM_INIT_AUTOMAKE HOT 1
- brew install for rlwrap fails on a mac (m1 arm) HOT 1
- rlwrap rewrites the input line right-shifted HOT 12
- rlwrap segfaults on test program HOT 1
- Right-shifted input (or double prompt) after accepting a line in bracketed-paste-mode with readline-8.2 HOT 19
- The rlwrap program occasionally fails on several Solaris machines creating a fault alert HOT 4
- programs (like php -a) that put even a dumb terminal in bracketed-paste mode confuse rlwrap HOT 1
- rlwrap kills forked children HOT 2
- [feature] shell completion HOT 3
- Minor issue about english HOT 1
- rlwrap -a bc duplicates the line to the right HOT 1
- configure cannot find readline in non-root install HOT 6
- -f . should fail silently if there is no history (yet) HOT 2
- rlwrap modifies a line after entering HOT 1
- main_loop: Assertion `!always_readline' failed HOT 3
- Doesn't really work well with fish
- RlwrapFilter.pm-manpage broken in wiki
- [QUESTION] Make sure command output has a newline at the end
- Rlwrap doesn't work from inside Emacs' vterm or term
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rlwrap.