readline: readline_callback_read_char() called wit...
# xschem
d
readline: readline_callback_read_char() called with no handler! Thread 1 "xschem" received signal SIGABRT, Aborted. ... HEAD~5a4b2cc6~20240425 built with readline-7.0-10.el8.x86_64 tcl-tclreadline-2.1.0-16.el8.x86_64 (gdb) bt ... #12 0x00007ffff65b7927 in Tcl_GlobalEval () from /lib64/libtcl8.6.so #13 0x000000000048d815 in tcleval (str=0x527268 "text_line {Input property:} 0 normal") at scheduler.c:6051 #14 0x00000000004ad811 in edit_wire_property () at editprop.c:1038 Triggered this one a few times, wasn't sure how/why, rebuilt in debug mode, no issues for a few days 🙂 finally triggered it, but now I think it can be reproduced on demand Step are something like, open .sch, find/select a symbol, edit attributes (on symbol), change .sym file to non-exist file by removing directory component to path, click OK, use tclreadline stdin Go back reselect symbol, edit attributes (on symbol), change .sym file to be prefixed with ./ but do not press OK, then go back to use tclreadline stdin and find it SIGABRT (with edit_properties dialog window open)
s
@dlmiles Yes this is a tclreadline issue, When a dialog box is open do not enter commands in the xschem prompt. I wrote to the tclreadline developers , neger got an answer. Fix: don't use tclreadline (xschem -r)
I plan to remove tclreadline in the future (so one less dependency) , if I find a simple way to enable command history in a xschem tcl console.
d
Thanks for the reply, maybe FlightAware fork of tclreadline is a maintained one (just a hassle for users to custom build it) if less buggy Yes the tcl console inside GUI would be more ideal. Does the command completion function work ? or is the only main feature the TCL command history (which I assume you mean by that a shell like up/down/home/end/Ctrl-W etc... bindings as well)
Worth a warning on startup if its an unresolvable crashing issue
Copy code
WARNING: tclreadline active, see tclreadline/issue/12345 recommend disabling with -r
s
the main feature I need is to recall older commands (with arrow up or similar keybindings). Autocompletion and stuff like that was already disabled because it was another source of crashes or just autocompletes commands the wrong way, so useless. Another issue with tclreadline is that you can't use the
!
character since it is used for history (like in a shell) however
!
is used in tcl expressions. This command:
if {!$a} { puts "Zero"}
just does not work with tclreadline. this is more than enough to drop tclreadline altogether.
@dlmiles one interesting way to enable command history without tclreadline is to use rlwrap (readline wrapper):
rlwrap xschem -r
will do the job without tclreadline. I like the Unix / Kiss approach of doing one thing and (does it?) doing it well , and rlwrap (maybe) does exactly that.
d
Dirty hack of the day ?
history_expansion_char = '\0'
needs main executable to linked
-lreadline -ldl
but both libraries can become a configure dependency making both optional. Maybe if cleaned up can
#ifdef HAS_DLFCN_H
around relevant parts instead of letting tclreadline load it at runtime.
Copy code
diff --git a/src/xinit.c b/src/xinit.c
index aace3665..4eeeb8ef 100644
--- a/src/xinit.c
+++ b/src/xinit.c
@@ -24,6 +24,7 @@
 #ifdef __unix__
 #include <pwd.h> /* getpwuid */
 #endif
+#include <dlfcn.h>
 
 static int init_done=0; /* 20150409 to avoid double call by Xwindows close and TclExitHandler */
 static XSetWindowAttributes winattr;
@@ -2267,6 +2268,22 @@ void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h)
   }
 }
 
+static int fixup_readline(void)
+{
+  /* This dirty hack is doing the equivalent: */
+  /* <readline/history.h> */
+  /*extern char history_expansion_char;*/
+  /*history_expansion_char = '\0'*/
+  {
+    char *sym = (char *) dlsym((void*)0, "history_expansion_char");
+    if(sym) {
+      dbg(1, "readline history_expansion_char=0 patched\n");
+      *sym = '\0'; /* prevents '!' history expansion in tcl expressions */
+    }
+  }
+  return TCL_OK;
+}
+
 static void tclmainloop(void)
 {
   while(1) Tcl_DoOneEvent(TCL_ALL_EVENTS);
@@ -2567,6 +2584,8 @@ int Tcl_AppInit(Tcl_Interp *inter)
  /*                                */
  Tcl_CreateCommand(interp, "xschem",   (myproc *) xschem, NULL, NULL);
 
+ Tcl_CreateCommand(interp, "fixup_readline",   (myproc *) fixup_readline, NULL, NULL);
+
  dbg(1, "Tcl_AppInit(): done step a1 of xinit()\n");
 
 
@@ -3014,6 +3033,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
    tcleval( "if {![catch {package require tclreadline}] && $tcl_interactive} "
      "{::tclreadline::readline builtincompleter 0;"
       "::tclreadline::readline customcompleter completer;"
+      "fixup_readline;"
       "::tclreadline::Loop }" 
    );
  }
s
Thank you, @dlmiles I keep this patch as a possible improvement. Another big issue I have with xschem+tclreadline is the following: • start xschem with tclreadline enabled prompt. • load a schematic • double click an instance to bring up the edit attributes dialog box • Press a couple of times the Enter key in the xschem console. Application crashes and I get this abort message:
Copy code
xschem [~] 

readline: readline_callback_read_char() called with no handler!
Aborted
Never been able to fix this. If I don't get a work around on this I think it is fair to remove tclreadline altogether, I am really pissed off for all the issues it brings in. On the other side rlwrap seems to work fine.
d
Yeah that is my original bug report of this thread 🙂 The patch shows the issue with
!
is GNU readline not tclreadline (which is a wrapper with TCL hooks/API/bindings and some more useful defaults in configuration), underneath it still defers the implementation to GNU readline via the tclreadline wrapper and it is this that does the history
!
expansion, so even using
rlwrap
maybe have this unwanted features. But it seems a configurable thing (exported from
history.h
), even if not totally documented. There is also
inputrc
file configuration possibility to modify the bindings for xschem as wanted, especially if it allows for use of custom path
$HOME/.xschem/inputrc
. If not then it is another additional step for installation to have the user append conf to
$HOME/.inputrc
which may not be desirable.
Am agreeing that maybe
tclreadline
does not do much (as in provide much net positive), is not maintained (or at least the standard version found in a linux distribution is not maintained). So direct use of
readline
could use a less hackey patch.
s
@dlmiles the rlwrap method does not mess with ! (unless may be it is the first character). The following works as expected:
Copy code
schippes@asus:~$ rlwrap xschem -r
% set a 1
1
% if {!$a} {puts zero}
% set a 0
0
% if {!$a} {puts zero}
zero
So I also agree, direct use of libreadline should be the best option...
d
Understand, I have never use
rlwrap
before, so do not know its specifics, just demonstraing the
!
is configurable. Ideally I think I am still thinking that using
readline
as a dependency but directly then converting it to run inside GUI shell popup window is the most ideal situation, as I don't think you need to re-write the readline features, just bind the X.11 keypress events to the readline and provide a redraw mechanism
Step1 maybe to use the command line shell with readline (removing tclreadline use), then Step2 shell like experience inside GUI Step3 convert this shell to bind readline directly inside GUI
s
Yes, I already wrote a small test program to familiarize with readline(), basically I could remove tclreadline, and add my own readline loop, feeding input lines to the tcl parser.