első ötletek:
1. bash újrafordítása -g opcióval
2. megnézni a source-ban, mit csinál SIGWINCH esetén
20131017.1840 Írtam valamit tanulságul ide (a harmadik a 'vegyes problémák' rovatban):
http://web.axelero.hu/lzsiga/terminal.html#S0013
20130818.1615: Válasz a fejlesztőtől:
Readline-6.3 has undergone fairly extensive changes to signal handling,
and does minimal work in the signal handler itself. The real work is now
deferred until it's `safe' to do it. Bash-4.3 has the same sort of changes.
- NevemTeve blogja
- A hozzászóláshoz be kell jelentkezni
- 1108 megtekintés
Hozzászólások
van egy variables.c:sh_set_lines_and_columns (lines, cols) függvény, az hívódott:
#0 sh_set_lines_and_columns (lines=32, cols=90) at variables.c:875
#1 0x100cccdc in get_new_window_size (from_sig=0, rp=0x0, cp=0x0) at winsize.c:73
#2 0x1000c2b0 in shell_getc (remove_quoted_newline=1) at ./parse.y:1882
#3 0x1001275c in read_token_word (character=115) at ./parse.y:3674
#4 0x1000e71c in read_token (command=0) at ./parse.y:2708
#5 0x1000d190 in yylex () at ./parse.y:2208
#6 0x10007d80 in yyparse () at y.tab.c:1584
#7 0x100cd684 in parse_command () at eval.c:222
#8 0x100cd818 in read_command () at eval.c:266
#9 0x100cd2c4 in reader_loop () at eval.c:132
#10 0x10001354 in main (argc=1, argv=0x2ff22640, env=0x2ff22648) at shell.c:715
- A hozzászóláshoz be kell jelentkezni
Debuggerel futtatva SIGSEGV van:
#0 0x1002e974 in add_or_supercede_exported_var (
assign=0x20081628 "_=/usr/local/bin/stty", do_alloc=0) at variables.c:3191
#1 0x1002f33c in update_export_env_inplace (env_prefix=0x100d8534 <__dbsubn+7980> "_=",
preflen=2, value=0x200815b8 "/usr/local/bin/stty") at variables.c:3330
#2 0x1002f3b8 in put_command_name_into_env (
command_name=0x200815b8 "/usr/local/bin/stty") at variables.c:3338
#3 0x100252b8 in execute_disk_command (words=0x20070f68, redirects=0x0,
command_line=0x200770a8 "stty", pipe_in=-1, pipe_out=-1, async=0,
fds_to_close=0x20073158, cmdflags=0) at execute_cmd.c:3660
#4 0x10023c94 in execute_simple_command (simple_command=0x20073c48, pipe_in=-1,
pipe_out=-1, async=0, fds_to_close=0x20073158) at execute_cmd.c:3066
#5 0x1001d1d0 in execute_command_internal (command=0x20073138, asynchronous=0,
pipe_in=-1, pipe_out=-1, fds_to_close=0x20073158) at execute_cmd.c:678
#6 0x1001c5ec in execute_command (command=0x20073138) at execute_cmd.c:352
#7 0x100cd3a4 in reader_loop () at eval.c:147
#8 0x10001354 in main (argc=1, argv=0x2ff22640, env=0x2ff22648) at shell.c:715
A probléma oka, hogy a 'variables.c'::export_env felülíródott valamikor:
(gdb) print 'variables.c'::export_env
$29 = (char **) 0x20072e98
(gdb) print (char *)'variables.c'::export_env
$30 = 0x20072e98 "#1382001761"
- A hozzászóláshoz be kell jelentkezni
A szerveren a "shopt" mit mond a checkwinsize valtozo allapotara, on vagy off? Ha on, es kikapcsolod, akkor is fagyik?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Alapban 'off' volt, és az átállítása sem változtatott a hibán; viszont segített észrevenni egy érdekes jelenséget: ha átméretezés után belső parancsot futtatok (pl shopt, help, set), akkor nem fagy!
- A hozzászóláshoz be kell jelentkezni
egy lehetséges debuggolási menet:
dir ../readline-6.2
display 'variables.c'::export_env[0]
break sh_set_lines_and_columns
handle SIGWINCH stop
- A hozzászóláshoz be kell jelentkezni
Közben megkapta a szemem egy apróság: a readline (az én hibámból) -D_THREAD_SAFE nélkül volt fordítva (ezt onnen lehet tudni, hogy _Errno függvényt kellene használjon a libc-ből, nem pedig errno változót). Valószínűleg semmi köze semmihez, de akkor már ezt is javítom.
- A hozzászóláshoz be kell jelentkezni
Most nézzük mi történik SIGWINCH-nél:
#0 sh_set_lines_and_columns (lines=32, cols=90) at shell.c:130
#1 0x2003c4f8 in _rl_get_screen_size (tty=0, ignore_env=1) at terminal.c:299
#2 0x2003c878 in rl_resize_terminal () at terminal.c:353
#3 0x200305fc in rl_sigwinch_handler (sig=28) at signals.c:260
(gdb) l shell.c:sh_set_lines_and_columns
121 /* Set the environment variables LINES and COLUMNS to lines and cols,
122 respectively. */
123 void
124 sh_set_lines_and_columns (lines, cols)
125 int lines, cols;
126 {
127 char *b;
128
129 #if defined (HAVE_SETENV)
130 b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
131 sprintf (b, "%d", lines);
132 setenv ("LINES", b, 1);
133 xfree (b);
134
135 b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
136 sprintf (b, "%d", cols);
137 setenv ("COLUMNS", b, 1);
138 xfree (b);
139 #else /* !HAVE_SETENV */
140 # if defined (HAVE_PUTENV)
141 b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
142 sprintf (b, "LINES=%d", lines);
143 putenv (b);
144
145 b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
146 sprintf (b, "COLUMNS=%d", cols);
147 putenv (b);
148 # endif /* HAVE_PUTENV */
149 #endif /* !HAVE_SETENV */
150 }
- A hozzászóláshoz be kell jelentkezni
Úgy látom, a HAVE_SETENV ágba megy bele. (a setenv a stdlib.h-ból jön, ha _XOPEN_SOURCE >= 600)
- A hozzászóláshoz be kell jelentkezni
Most pillanatnyilag úgy tűnik, hogy a 137-nél belemegy a setenv-be, és amikor kijön belőle, az export_env már felül is van írva.
Breakpoint 3, 0xd03472d0 in setenv () from /usr/lib/libc.a(shr.o)
1: 'variables.c'::export_env[0] = 0x200d29b8 "AUTHSTATE=compat"
(gdb) s
Single stepping until exit from function setenv,
which has no line number information.
sh_set_lines_and_columns (lines=32, cols=90) at shell.c:138
138 xfree (b);
1: 'variables.c'::export_env[0] = 0x200d2fb0 ""
Itt kissé meg is akadtam... az ugyanis biztos, hogy én a libc.setenv forrását nem látom...
- A hozzászóláshoz be kell jelentkezni
a setenv a putenv-et hívja, akkor romlik el a változóm
=> 0xd0347424 <setenv+372>: bl 0xd02e454c <putenv>
1: 'variables.c'::export_env[0] = 0x200d29b8 "AUTHSTATE=compat"
(gdb) ni
0xd0347428 in setenv () from /usr/lib/libc.a(shr.o)
2: x/i $pc
=> 0xd0347428 <setenv+376>: oril r0,r0,0
1: 'variables.c'::export_env[0] = 0x200d2fb0 ""
A putenv pedig realloc-ot hív
2: x/i $pc
=> 0xd02e45b0 <putenv+100>: l r3,0(r27)
1: 'variables.c'::export_env[0] = 0x200d29b8 "AUTHSTATE=compat"
(gdb) ni
0xd02e45b4 in putenv () from /usr/lib/libc.a(shr.o)
2: x/i $pc
=> 0xd02e45b4 <putenv+104>: bl 0xd01ef4d0 <realloc>
1: 'variables.c'::export_env[0] = 0x200d29b8 "AUTHSTATE=compat"
(gdb) print (char *)$r3
$6 = 0x200d2e98 " \r)¸ \r)Ø \r+Ø \r,( \r,\210 \r,¸ \r,è \r1x \r1¨ \r1ø \r2( \r2h \r2\210 \r2¨ \r2Ø \r3\030 \r3h \r4\030 \r4H \r4h \r4\230 \r4è \r5\b \r58 \r5x \r5\230 \r5È \r5ø \r6( \r6h \r6\230 \r7\230 \r7È \r8\b \r8( \r,H \r8H \r8h \r8¸ \016\030x \016\030¨ \r8Ø \016\030è \016\031\b \016\031\070 \016\031x \016\031¨ \016\031Ø \016\032\b \016\032\070"...
(gdb) print $r4
$7 = 220
(gdb) ni
0xd02e45b8 in putenv () from /usr/lib/libc.a(shr.o)
2: x/i $pc
=> 0xd02e45b8 <putenv+108>: oril r0,r0,0
1: 'variables.c'::export_env[0] = 0x200d2fb0 ""
- A hozzászóláshoz be kell jelentkezni
Csak úgy megemlítem, hogy az info libc ilyen érdekes dolgokat mond a signal-handlerekről:
* On most systems, `malloc' and `free' are not reentrant, because
they use a static data structure which records what memory blocks
are free. As a result, no library functions that allocate or free
memory are reentrant. This includes functions that allocate space
to store a result.
- A hozzászóláshoz be kell jelentkezni
Végül is ilyesmit alkottam, átmenetileg jó lesz (readline-6.2/shell.c/sh_set_lines_and_columns):
/* Set the environment variables LINES and COLUMNS to lines and cols,
respectively. */
void
sh_set_lines_and_columns (lines, cols)
int lines, cols;
{
char *b;
if (getenv ("LINES") && getenv ("COLUMNS")) {
#if defined (HAVE_SETENV)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", lines);
setenv ("LINES", b, 1);
xfree (b);
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", cols);
setenv ("COLUMNS", b, 1);
xfree (b);
#else /* !HAVE_SETENV */
# if defined (HAVE_PUTENV)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
sprintf (b, "LINES=%d", lines);
putenv (b);
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
sprintf (b, "COLUMNS=%d", cols);
putenv (b);
# endif /* HAVE_PUTENV */
#endif /* !HAVE_SETENV */
}
}
Megboldolva a saját kiegészítésem.
- A hozzászóláshoz be kell jelentkezni
Mondjuk az lehet, hogy én vagyok hülye, de mintha a readline-6.3 is pont azt csinálná, mint a readline-6.2:
beesik a SIGWINCH, elindul a terminal.c:rl_resize_terminal
az meghívja a terminal.c:_rl_get_screen_size-t
az pedig a shell.c:sh_set_lines_and_columns-t
aki pedig hívja a setenv-et.
Amig ígért a derék fejlesztő, hogy nem fog hívni...
Namost van valami mese, hogy ha a bash-ba belegyógyított readline-t használjuk, akkor másképp működ(het)nek a dolgok... hadd ne próbáljam ki, nekem a shared lib pont azért shared lib, hogy azt használja a bash, a gdb, a php vagy aki akarja
Szerk: olyasmit lehetne haxorizálni, hogy
1. sose baktassa a kérdés változókat
2. baktassa, de csak ha már előzőleg voltak ilyen változók (hogy ne kelljen realloc-olni az environ(7)-t) és akkor is csak putenv-et szíveskedjen használni (az nem másolja le a paraméterét, hanem közvetlenül illeszti be az environment-be; szerencsére annyit megtett a derék fejlesztő, hogy 6.3-ban statikus buffereket vett fel, a 6.2-ben használt malloc helyett)
- A hozzászóláshoz be kell jelentkezni
Visszaírt. Én tévedtem: nem signal-handlerből hívja. És mégis fagyizik. Bameg.
2: x/i $pc
=> 0xd1184f20 <sh_set_lines_and_columns+104>: lil r5,1
1: export_env[0] = 0x2003fa78 "AUTHSTATE=compat"
(gdb)
0xd1184f24 138 setenv ("COLUMNS", setenv_buf, 1);
2: x/i $pc
=> 0xd1184f24 <sh_set_lines_and_columns+108>: bl 0xd1185260 <setenv>
1: export_env[0] = 0x2003fa78 "AUTHSTATE=compat"
(gdb) ni
0xd1184f28 138 setenv ("COLUMNS", setenv_buf, 1);
2: x/i $pc
=> 0xd1184f28 <sh_set_lines_and_columns+112>: l r2,20(r1)
1: export_env[0] = 0x2004f900 " \004"
Belemegy a setenv-be, és mire kijön, az export_env el van csesződve...
- A hozzászóláshoz be kell jelentkezni
Az 1) nem jo megoldas, mert ezek a valtozok rettenetesen hasznosak scriptelesnel, en pl. eleg sokszor hasznalom oket, ha valami alapszintu CLI UI-t kell osszerakni.
Nem olvastam mindent vissza, konkretan miert is baj, hogy van egy setenv(3)?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
A gond nagyobb, mint hittem... alapvetően másképp van a shared libek lelki világa AIX-en, mint linux-on.
Ezt persze eddig is tudtam, de most nagyon megtudtam, hogy hol lakik a Unixok istene... A libreadline.so koncepciója az, hogy ha van neki egy 'setenv' nevű extern függvénye, az majd futáskor rezolválódik valahonnan, vagy a főprogramból, vagy máshonnan, majd kialakul. Sőt, ha van neki egy saját 'xmalloc' függvénye, azt is lecserélheti a hívó azonos nevű függvénye. Vagy egy másik shared lib azonos nevű függvénye. Ahogy esik, úgy puffan.
Az előbbi feature még menne, AIX-on is van dinamikus linkelés (-brtllib opció a főprogramban, -berok a shared lib-ben), na de az utóbbi...
Most abban bízom, hogy akkor menjen a bash a beledrótozott readline-nal, és legyen öröm+boldogság, de vajon a többi readline-t használó program (gdb, pl) mit csinál?
(Pótkérdés: a 'php -a' miért nem readline-ozik nekem AIX-en, linuxon meg igen? Mindkettő házi fordítású... Na jó, ezt majd legközelebb...)
- A hozzászóláshoz be kell jelentkezni