[sisyphus] Про htop

Sergey Vlasov vsu на altlinux.ru
Пн Дек 16 20:16:23 MSK 2013


On Sun, Dec 15, 2013 at 05:22:43PM +0400, Alexei V. Mezin wrote:
> 15.12.2013 17:00, Alexei V. Mezin пишет:
> [alexei на bigbear ncurses-5.9]$ echo $LINES $COLUMNS
> 56 154
> 
> Я так понял, что bash выставляет эти переменные самостоятельно. А из man 
> resizeterm
> 
> If the environment variables LINES or COLUMNS are set, this overrides 
> the library's use of the window size obtained from the  operating 
> system.  Thus, even if a SIGWINCH is received, no screen size change may 
> be recorded.
> 
> То есть пока bash будет выставлять такие переменные, htop нормально 
> работать не будет. Или перед запуском надо делать unset.
> 
> Значит это не баг, а просто htop и подобные плохо написаны, надо 
> переделывать на использование сигналов напрямую.

На самом деле, возможно, это баг в bash (точнее, во взаимодействии bash с
внешней библиотекой libreadline).

Дело в том, что в libreadline есть функция sh_set_lines_and_columns(),
которая как раз и добавляет в окружение текущего процесса переменные LINES
и COLUMNS:

  http://git.altlinux.org/gears/r/readline.git?p=readline.git;a=blob;f=readline/shell.c;h=346f8113d43d742191f34f431d55e94316e4431d;hb=bc8ee94c5760cc286148d7ab25f2606c0eeeb52a#l121

Однако ближе к началу файла shell.c есть следующий комментарий:

 88 /* All of these functions are resolved from bash if we are linking readline
 89    as part of bash. */

  http://git.altlinux.org/gears/r/readline.git?p=readline.git;a=blob;f=readline/shell.c;h=346f8113d43d742191f34f431d55e94316e4431d;hb=bc8ee94c5760cc286148d7ab25f2606c0eeeb52a#l88

И действительно, в самом bash тоже определяется функция
sh_set_lines_and_columns():

  http://git.altlinux.org/gears/b/bash.git?p=bash.git;a=blob;f=bash/variables.c;h=1c782534e22d77e492cb66cad6d8666c9a911e23;hb=ab284e13150cb2edf3345256c6ddd919babf3a24#l864

В отличие от реализации в libreadline, функция из bash использует не
setenv(), а внутреннюю функцию bash bind_variable(), которая устанавливает
внутреннюю переменную shell, по умолчанию не экспортирующуюся в дочерние
процессы; именно такое поведение можно наблюдать сейчас в zsh - в скриптах
можно использовать переменные $LINES и $COLUMNS, но zsh не передаёт эти
переменные другим процессам, если не выполнить export явно.

Однако в ALT пакеты bash и libreadline собраны таким образом, что при
вызове sh_set_lines_and_columns() из функций libreadline всегда вызывается
реализация этой функции внутри libreadline - перекрытие её реализацией из
bash, предполагавшееся разработчиками, не выполняется.

$ gdb bash
GNU gdb (GDB) 7.5.0.20121002-alt3 (ALT Linux)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-alt-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /bin/bash...Reading symbols from /usr/lib/debug/bin/bash.debug...done.
done.
(gdb) b sh_set_lines_and_columns
Breakpoint 1 at 0x42bee0: file ../variables.c, line 869.
(gdb) r
Starting program: /bin/bash 

Breakpoint 1, sh_set_lines_and_columns (lines=40, cols=80)
    at ../variables.c:869
869	{
(gdb) bt
#0  sh_set_lines_and_columns (lines=40, cols=80) at ../variables.c:869
#1  0x000000000046a395 in get_new_window_size (from_sig=from_sig на entry=0, 
    rp=rp на entry=0x0, cp=cp на entry=0x0) at ../../../lib/sh/winsize.c:75
#2  0x00000000004331fb in get_tty_state () at ../jobs.c:1968
#3  get_tty_state () at ../jobs.c:1938
#4  0x000000000043380d in initialize_job_control (force=force на entry=0)
    at ../jobs.c:3598
#5  0x00000000004166c6 in shell_initialize () at ../shell.c:1673
#6  0x0000000000414c33 in main (argc=1, argv=0x7fffffffe4c8, 
    env=0x7fffffffe4d8) at ../shell.c:543
(gdb) c
Continuing.

Breakpoint 1, sh_set_lines_and_columns (lines=40, cols=80) at ../shell.c:126
126	../shell.c: Нет такого файла или каталога.
(gdb) bt
#0  sh_set_lines_and_columns (lines=40, cols=80) at ../shell.c:126
#1  0x00007ffff7bc1d2d in _rl_get_screen_size (tty=<optimized out>, 
    ignore_env=0) at ../terminal.c:299
#2  0x00007ffff7bc23ca in _rl_init_terminal_io (terminal_name=<optimized out>)
    at ../terminal.c:521
#3  0x00007ffff7bc253b in _rl_set_screen_size (rows=40, cols=<optimized out>)
    at ../terminal.c:312
#4  0x000000000046a3a3 in get_new_window_size (from_sig=from_sig на entry=0, 
    rp=rp на entry=0x0, cp=cp на entry=0x0) at ../../../lib/sh/winsize.c:77
#5  0x00000000004331fb in get_tty_state () at ../jobs.c:1968
#6  get_tty_state () at ../jobs.c:1938
#7  0x000000000043380d in initialize_job_control (force=force на entry=0)
    at ../jobs.c:3598
#8  0x00000000004166c6 in shell_initialize () at ../shell.c:1673
#9  0x0000000000414c33 in main (argc=1, argv=0x7fffffffe4c8, 
    env=0x7fffffffe4d8) at ../shell.c:543

Видно, что во втором по порядку вызове, сделанном изнутри libreadline,
была вызвана именно реализация из libreadline, а не из bash (имена файлов
отличаются).

Кстати, аналогичная проблема наблюдается и в самом gdb, который тоже
использует libreadline:

  https://lists.gnu.org/archive/html/bug-readline/2013-09/msg00004.html

В некоторых других дистрибутивах как минимум bash ведёт себя правильнее
(не экспортирует переменные LINES и COLUMNS):

  http://lists.gnu.org/archive/html/bug-bash/2013-07/msg00056.html
  http://lists.gnu.org/archive/html/bug-bash/2013-07/msg00063.html
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : отсутствует
Тип     : application/pgp-signature
Размер  : 190 байтов
Описание: Digital signature
Url     : <http://lists.altlinux.org/pipermail/sisyphus/attachments/20131216/b8a19c9a/attachment.bin>


Подробная информация о списке рассылки Sisyphus