unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
@ 2024-09-04  6:09 Daniel Clemente
       [not found] ` <handler.73022.B.172543028723315.ack@debbugs.gnu.org>
  2024-09-04  7:28 ` bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 2 replies; 35+ messages in thread
From: Daniel Clemente @ 2024-09-04  6:09 UTC (permalink / raw)
  To: 73022

Continuing from this comment at
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=71289:

> That's another problem.  There seems to be some disconnect, time-wise,
> in reallocating frame matrices and sub-allocating window matrices from
> the frame matrices, and the crash happens when the check is done
> in-between those two.

In particular, I found a case in which an assert fails because the
window row glyph memory is not contained in the frame row glyph
memory.

It happens in a recent build (99a03ddb2d4) built without X support.
I'm running it in a urxvt terminal but it happens in xterm too. It
crashes both with and without glyph debug. This is not related to
garbage collection like bug 71289.

To reproduce:
1. Open emacs -Q
2. Press C-x 2 to split the frame (top/bottom)
3. Make the terminal very small (I slowly resize the X window that's
running urxvt, to the minimum size, 1 row and 2 columns in my case).
This shrinking process alone can produce the crash when the window is
around 5 lines high
4. It always crashes in my case. If it doesn't, make the terminal
larger again, and repeat the resizing for some seconds until it
crashes

Note that the C-x 2 is required. The problem doesn't happen with a
left/right split (C-x 3). But it happens after a C-x 3 C-x 2.

Manually resizing is enough to trigger the problem. But it's also
possible to automate the resizing with something like this (change the
first part to find the window ID):   EC=$(xdotool search --name '^\gdb
src/emacs') && echo $EC && while :; do for height_px in `seq 275 -25
10`; do xdotool windowsize $EC $((height_px+5)) $height_px; sleep
0.001; done;   for height_px in `seq 1 25 400`; do xdotool windowsize
$EC $((height_px+5)) $height_px; sleep 0.1; done;     sleep 0.3 &&
done


(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>,
signo=signo@entry=6, no_tid=no_tid@entry=0) at
./nptl/pthread_kill.c:44
#1  0x00007ffff554ae8f in __pthread_kill_internal (signo=6,
threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  0x00007ffff54fbfb2 in __GI_raise (sig=6) at ../sysdeps/posix/raise.c:26
#3  0x000055555568d0c2 in terminate_due_to_signal (sig=6,
backtrace_limit=2147483647) at emacs.c:469
#4  0x000055555573de15 in die (
    msg=0x555555856798 "frame_size_change_delayed (XFRAME (w->frame))
|| glyph_row_slice_p (window_row, frame_row)",
    file=0x555555856231 "dispnew.c", line=2647) at alloc.c:8058
#5  0x000055555558b697 in build_frame_matrix_from_leaf_window
(frame_matrix=0x5555560fed00, w=0x55555603cca8) at dispnew.c:2647
#6  0x000055555558b154 in build_frame_matrix_from_window_tree
(matrix=0x5555560fed00, w=0x55555603cca8) at dispnew.c:2536
#7  0x000055555558b13f in build_frame_matrix_from_window_tree
(matrix=0x5555560fed00, w=0x555556260390) at dispnew.c:2534
#8  0x000055555558b0e3 in build_frame_matrix (f=0x55555603ca88) at
dispnew.c:2520
#9  0x000055555558d0e3 in update_frame (f=0x55555603ca88,
force_p=true, inhibit_hairy_id_p=false) at dispnew.c:3336
#10 0x00005555555d0904 in redisplay_internal () at xdisp.c:17518
#11 0x00005555555d1244 in redisplay_preserve_echo_area (from_where=11)
at xdisp.c:17801
#12 0x00005555557f5893 in wait_reading_process_output (time_limit=97,
nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=0x0,
    wait_proc=0x0, just_wait_proc=0) at process.c:5584
#13 0x00005555555951d3 in sit_for (timeout=0x186, reading=true,
display_option=1) at dispnew.c:6335


This is the failing assertion in frame 5, dispnew.c:
(gdb) list
2642            }
2643
2644    #ifdef GLYPH_DEBUG
2645          /* Window row window_y must be a slice of frame row
2646             frame_y.  */
2647          eassert (frame_size_change_delayed (XFRAME (w->frame))
2648               || glyph_row_slice_p (window_row, frame_row));
2649
2650          /* If rows are in sync, we don't have to copy glyphs because
2651             frame and window share glyphs.  */


Both conditions:
  frame_size_change_delayed (XFRAME (w->frame)
  glyph_row_slice_p (window_row, frame_row)
are false. I don't know which one should be true in this case.

This is the part about being delayed.
(gdb) p delayed_size_change
$15 = false


glyph_row_slice_p contains this code:
  struct glyph *window_glyph_start = window_row->glyphs[0];
  struct glyph *frame_glyph_start = frame_row->glyphs[0];
  struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA];
  return (frame_glyph_start <= window_glyph_start
      && window_glyph_start < frame_glyph_end);

The first part of the condition is false:

(gdb) p frame_row->glyphs[0]
$24 = (struct glyph *) 0x7ffff0f414c0
(gdb) p window_row->glyphs[0]
$25 = (struct glyph *) 0x7ffff088b430
(gdb) p frame_row->glyphs[0] <= window_row->glyphs[0]
$26 = 0
(gdb)

The second part is true:

(gdb) p window_row->glyphs[0]
$29 = (struct glyph *) 0x7ffff088b430
(gdb) p frame_row->glyphs[LAST_AREA]
$30 = (struct glyph *) 0x7ffff0f41970
(gdb) p window_row->glyphs[0] < frame_row->glyphs[LAST_AREA]
$31 = 1
(gdb)


Since the second part is true, I'm guessing that the first part should
also be true. So the error lies in frame_glyph_start <=
window_glyph_start (it should be true and isn't), which means the
window row glyph memory is not contained in the frame row glyph
memory.

I can research this further as I learn about terminal code. I report
this here to separate this simple bug from bug 71289 which is about
GC.
Note that I'm not seeing the cmcheckmagic error mentioned in bug 71289
anymore. I may have seen it in an older build. They may still happen
if the build_frame_matrix_from_leaf_window error doesn't happen first.


Extra data (this is from a case in which I used the autoresizer):

(gdb) p (struct frame) w->frame
$14 = {
  header = {
    size = 93825003499509
  },
  name = XIL(0x555556240b1d),
  icon_name = XIL(0),
  title = XIL(0x55555620e445),
  last_mouse_device = XIL(0x7ffff4ac4307),
  focus_frame = XIL(0x7ffff4ac42ff),
  root_window = make_fixnum(22),
  selected_window = XIL(0),
  old_selected_window = make_fixnum(22),
  minibuffer_window = XIL(0x555556198ac5),
  param_alist = XIL(0x7ffff09bd523),
  scroll_bars = XIL(0),
  condemned_scroll_bars = XIL(0x555556198ac5),
  menu_bar_items = XIL(0x55555601341d),
  face_hash_table = XIL(0x55555601344d),
  menu_bar_vector = XIL(0x55555601347d),
  buffer_predicate = make_fixnum(1),
  buffer_list = XIL(0),
  buried_buffer_list = XIL(0x30),
  tool_bar_position = XIL(0),
  tab_bar_items = XIL(0x30),
  tool_bar_items = XIL(0),
  face_cache = 0x0,
  last_tab_bar_item = 0,
  menu_bar_items_used = 0,
  current_pool = 0x7ffff09bd4e3,
  desired_pool = 0x30,
  desired_matrix = 0x5555561fc7c4,
  current_matrix = 0x555556050b70,
  glyphs_initialized_p = false,
  resized_p = false,
  default_face_done_p = false,
  already_hscrolled_p = false,
  updated_p = false,
  fonts_changed = false,
  cursor_type_changed = false,
  redisplay = false,
  visible = 1,
  iconified = false,
  garbaged = true,
  wants_modeline = false,
  auto_raise = false,
  auto_lower = false,
  no_split = false,
  explicit_name = true,
  window_change = false,
  window_state_change = true,
  mouse_moved = false,
  pointer_invisible = false,
  frozen_window_starts = false,
  output_method = output_android,
  can_set_window_size = true,
  after_make_frame = false,
  tab_bar_redisplayed = true,
  tab_bar_resized = false,
--Type <RET> for more, q to quit, c to continue without paging--
  tool_bar_redisplayed = true,
  tool_bar_resized = false,
  inhibit_horizontal_resize = true,
  inhibit_vertical_resize = false,
  face_change = true,
  inhibit_clear_image_cache = false,
  new_size_p = true,
  was_invisible = false,
  select_mini_window_flag = true,
  change_stamp = 12,
  number_of_windows = 1,
  tab_bar_lines = 210,
  tab_bar_height = 0,
  n_tab_bar_rows = 1,
  n_tab_bar_items = 0,
  tool_bar_lines = 1,
  tool_bar_height = 22,
  n_tool_bar_rows = 2,
  n_tool_bar_items = 22,
  decode_mode_spec_buffer = 0x1600000002 <error: Cannot access memory
at address 0x1600000002>,
  insert_line_cost = 0x1600000001,
  delete_line_cost = 0x2,
  insert_n_lines_cost = 0x0,
  delete_n_lines_cost = 0x0,
  text_cols = 0,
  text_lines = 0,
  text_width = 0,
  text_height = 0,
  total_cols = 0,
  total_lines = 0,
  pixel_width = 1,
  pixel_height = 0,
  new_width = -1,
  new_height = -1,
  left_pos = 0,
  top_pos = 0,
  win_gravity = 0,
  size_hint_flags = 0,
  border_width = -1,
  child_frame_border_width = -1,
  internal_border_width = 1,
  right_divider_width = 1,
  bottom_divider_width = 0,
  left_fringe_width = 0,
  right_fringe_width = 0,
  fringe_cols = 0,
  menu_bar_lines = 0,
  menu_bar_height = 0,
  column_width = 0,
  line_height = 0,
  terminal = 0x0,
  output_data = {
    tty = 0x0,
    x = 0x0,
    w32 = 0x0,
    ns = 0x0,
    pgtk = 0x0,
    haiku = 0x0,
--Type <RET> for more, q to quit, c to continue without paging--
    android = 0x0
  },
  font_driver_list = 0xffffffff00000000,
  desired_cursor = NO_CURSOR,
  cursor_width = 0,
  blink_off_cursor = FILLED_BOX_CURSOR,
  blink_off_cursor_width = -1,
  config_scroll_bar_width = -1,
  config_scroll_bar_cols = 1,
  config_scroll_bar_height = -1,
  config_scroll_bar_lines = -1,
  cost_calculation_baud_rate = 624886,
  alpha = {1.4128247976246783e-309, 0},
  alpha_background = 3.1349799205870865e-318,
  gamma = 2.0000000223608367,
  extra_line_spacing = 1444514496,
  background_pixel = 0,
  foreground_pixel = 93825003500664
}



(gdb) p *window_row
$20 = {
  glyphs = {0x7ffff088b430, 0x7ffff088b430, 0x7ffff088b850, 0x7ffff088b850},
  used = {0, 22, 0, 0},
  hash = 122398255,
  x = 0,
  y = 0,
  pixel_width = 21,
  ascent = 0,
  height = 1,
  phys_ascent = 0,
  phys_height = 1,
  visible_height = 1,
  extra_line_spacing = 0,
  start = {
    pos = {
      charpos = 1,
      bytepos = 1
    },
    overlay_string_index = -1,
    string_pos = {
      charpos = -1,
      bytepos = -1
    },
    dpvec_index = -1
  },
  end = {
    pos = {
      charpos = 22,
      bytepos = 22
    },
    overlay_string_index = -1,
    string_pos = {
      charpos = -1,
      bytepos = -1
    },
    dpvec_index = -1
  },
  minpos = {
    charpos = 1,
    bytepos = 1
  },
  maxpos = {
    charpos = 22,
    bytepos = 22
  },
  overlay_arrow_bitmap = 0,
  left_user_fringe_bitmap = 0,
  right_user_fringe_bitmap = 0,
  left_fringe_bitmap = 0,
  right_fringe_bitmap = 0,
  left_user_fringe_face_id = 0,
  right_user_fringe_face_id = 0,
  left_fringe_face_id = 0,
  right_fringe_face_id = 0,
  left_fringe_offset = 0,
  right_fringe_offset = 0,
  fringe_bitmap_periodic_p = false,
  redraw_fringe_bitmaps_p = false,
--Type <RET> for more, q to quit, c to continue without paging--
  enabled_p = true,
  truncated_on_left_p = false,
  truncated_on_right_p = false,
  continued_p = true,
  displays_text_p = true,
  ends_at_zv_p = false,
  fill_line_p = false,
  indicate_empty_line_p = false,
  contains_overlapping_glyphs_p = false,
  full_width_p = false,
  mode_line_p = false,
  tab_line_p = false,
  overlapped_p = false,
  ends_in_middle_of_char_p = false,
  starts_in_middle_of_char_p = false,
  overlapping_p = false,
  mouse_face_p = false,
  ends_in_newline_from_string_p = false,
  exact_window_width_line_p = false,
  cursor_in_fringe_p = false,
  ends_in_ellipsis_p = false,
  indicate_bob_p = false,
  indicate_top_line_p = false,
  indicate_eob_p = false,
  indicate_bottom_line_p = false,
  reversed_p = false,
  stipple_p = false,
  continuation_lines_width = 0
}


(gdb) p *frame_row
$21 = {
  glyphs = {0x7ffff0f414c0, 0x7ffff0f414c0, 0x7ffff0f41970, 0x7ffff0f41970},
  used = {0, 0, 0, 0},
  hash = 0,
  x = 0,
  y = 0,
  pixel_width = 0,
  ascent = 0,
  height = 0,
  phys_ascent = 0,
  phys_height = 0,
  visible_height = 0,
  extra_line_spacing = 0,
  start = {
    pos = {
      charpos = 0,
      bytepos = 0
    },
    overlay_string_index = 0,
    string_pos = {
      charpos = 0,
      bytepos = 0
    },
    dpvec_index = 0
  },
  end = {
    pos = {
      charpos = 0,
      bytepos = 0
    },
    overlay_string_index = 0,
    string_pos = {
      charpos = 0,
      bytepos = 0
    },
    dpvec_index = 0
  },
  minpos = {
    charpos = 0,
    bytepos = 0
  },
  maxpos = {
    charpos = 0,
    bytepos = 0
  },
  overlay_arrow_bitmap = 0,
  left_user_fringe_bitmap = 0,
  right_user_fringe_bitmap = 0,
  left_fringe_bitmap = 0,
  right_fringe_bitmap = 0,
  left_user_fringe_face_id = 0,
  right_user_fringe_face_id = 0,
  left_fringe_face_id = 0,
  right_fringe_face_id = 0,
  left_fringe_offset = 0,
  right_fringe_offset = 0,
  fringe_bitmap_periodic_p = false,
  redraw_fringe_bitmaps_p = false,
--Type <RET> for more, q to quit, c to continue without paging--
  enabled_p = true,
  truncated_on_left_p = false,
  truncated_on_right_p = false,
  continued_p = false,
  displays_text_p = false,
  ends_at_zv_p = false,
  fill_line_p = false,
  indicate_empty_line_p = false,
  contains_overlapping_glyphs_p = false,
  full_width_p = false,
  mode_line_p = false,
  tab_line_p = false,
  overlapped_p = false,
  ends_in_middle_of_char_p = false,
  starts_in_middle_of_char_p = false,
  overlapping_p = false,
  mouse_face_p = false,
  ends_in_newline_from_string_p = false,
  exact_window_width_line_p = false,
  cursor_in_fringe_p = false,
  ends_in_ellipsis_p = false,
  indicate_bob_p = false,
  indicate_top_line_p = false,
  indicate_eob_p = false,
  indicate_bottom_line_p = false,
  reversed_p = false,
  stipple_p = false,
  continuation_lines_width = 0
}
(gdb)



In GNU Emacs 31.0.50 (build 3, x86_64-pc-linux-gnu) of 2024-09-01 built on sonn
Repository revision: 99a03ddb2d43d67577814b96e40ec069739b6421
Repository branch: master
System Description: Devuan GNU/Linux 5 (daedalus)

Configured using:
 'configure --prefix=/opt/dc/emacs/ --without-lcms2
--without-libsystemd --without-dbus
 --without-sound --with-mailutils --with-native-compilation
--without-modules --with-x-toolkit=no
 --without-xim --without-imagemagick --without-xft --without-harfbuzz
--without-libotf
 --without-xwidgets --without-xpm --with-tiff=no --without-tiff
--without-jpeg --without-gif
 --without-png --without-webp --without-rsvg --without-cairo
--without-x 'CFLAGS=-g3 -O3''

Configured features:
GMP GNUTLS LIBSELINUX LIBXML2 NATIVE_COMP NOTIFY INOTIFY PDUMPER
SECCOMP SQLITE3 THREADS XIM ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=SCIM
  locale-coding-system: utf-8-unix

Major mode: Dired by name

Minor modes in effect:
  xterm-mouse-mode: t
  server-mode: t
  gnus-dired-mode: t
  savehist-mode: t
  recentf-mode: t
  hexl-follow-ascii: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  async-bytecomp-package-mode: t
  jdecomp-mode: t
  projectile-mode: t
  override-global-mode: t
  rcirc-track-minor-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  unpackaged/org-export-html-with-useful-ids-mode: t
  minibuffer-depth-indicate-mode: t
  global-so-long-mode: t
  display-time-mode: t
  global-hl-line-mode: t
  xclip-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  minibuffer-regexp-mode: t
  buffer-read-only: t
  column-number-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/w/helm/helm-files hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-files
/w/helm/helm-comint hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-comint
/w/helm/helm-elisp-package hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-elisp-package
/w/helm/helm-external hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-external
/w/helm/helm-easymenu hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-easymenu
/w/helm/helm-font hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-font
/w/helm/helm-imenu hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-imenu
/w/helm/helm-x-files hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-x-files
/w/helm/helm-regexp hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-regexp
/w/helm/helm-net hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-net
/w/helm/helm-ring hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-ring
/w/helm/helm-find hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-find
/w/helm/helm-misc hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-misc
/w/helm/helm-occur hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-occur
/w/helm/helm-sys hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-sys
/w/helm/helm-types hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-types
/w/helm/helm-elisp hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-elisp
/w/helm/helm-adaptive hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-adaptive
/w/helm/helm-shell hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-shell
/w/helm/helm-id-utils hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-id-utils
/w/helm/helm-bookmark hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-bookmark
/w/helm/helm-mode hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-mode
/w/helm/helm-eshell hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-eshell
/w/helm/helm-dabbrev hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-dabbrev
/w/helm/helm-grep hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-grep
/w/helm/helm-color hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-color
/w/helm/helm-help hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-help
/w/helm/helm-buffers hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-buffers
/w/helm/helm-locate hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-locate
/w/helm/helm-tags hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-tags
/w/helm/helm-autoloads hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-autoloads
/w/helm/helm-info hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-info
/w/helm/helm-semantic hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-semantic
/w/helm/helm-command hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-command
/w/helm/helm-utils hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-utils
/w/helm/helm-eval hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-eval
/w/helm/helm-for-files hides
/home/dc/.emacs.d/elpa/helm-20191101.641/helm-for-files
/w/helm/helm-man hides /home/dc/.emacs.d/elpa/helm-20191101.641/helm-man
/w/helm/helm-multi-match hides
/home/dc/.emacs.d/elpa/helm-core-20191031.1931/helm-multi-match
/w/helm/helm-lib hides /home/dc/.emacs.d/elpa/helm-core-20191031.1931/helm-lib
/w/helm/helm-source hides
/home/dc/.emacs.d/elpa/helm-core-20191031.1931/helm-source
/w/helm/helm hides /home/dc/.emacs.d/elpa/helm-core-20191031.1931/helm
/home/dc/.emacs.d/elpa/transient-20220717.1713/transient hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/transient
/w/org-mode/lisp/org-fold-core hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-fold-core
/w/org-mode/lisp/ob-haskell hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-haskell
/w/org-mode/lisp/org-plot hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-plot
/w/org-mode/lisp/ox-icalendar hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-icalendar
/w/org-mode/lisp/org-footnote hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-footnote
/w/org-mode/lisp/org-archive hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-archive
/w/org-mode/lisp/ob-exp hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-exp
/w/org-mode/lisp/ob-octave hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-octave
/w/org-mode/lisp/oc-natbib hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc-natbib
/w/org-mode/lisp/org-num hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-num
/w/org-mode/lisp/ob-processing hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-processing
/w/org-mode/lisp/org-mouse hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-mouse
/w/org-mode/lisp/ob-core hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-core
/w/org-mode/lisp/ob-awk hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-awk
/w/org-mode/lisp/org-table hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-table
/w/org-mode/lisp/org-lint hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-lint
/w/org-mode/lisp/oc-basic hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc-basic
/w/org-mode/lisp/ob-scheme hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-scheme
/w/org-mode/lisp/ox-latex hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-latex
/w/org-mode/lisp/org-loaddefs hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-loaddefs
/w/org-mode/lisp/ob-table hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-table
/w/org-mode/lisp/ob-shell hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-shell
/w/org-mode/lisp/org hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/org
/w/org-mode/lisp/ol-man hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-man
/w/org-mode/lisp/ol-rmail hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-rmail
/w/org-mode/lisp/ox-man hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-man
/w/org-mode/lisp/org-cycle hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-cycle
/w/org-mode/lisp/org-datetree hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-datetree
/w/org-mode/lisp/ol-mhe hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-mhe
/w/org-mode/lisp/ob-css hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-css
/w/org-mode/lisp/org-fold hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-fold
/w/org-mode/lisp/ob-lilypond hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-lilypond
/w/org-mode/lisp/ob-comint hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-comint
/w/org-mode/lisp/ob-plantuml hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-plantuml
/w/org-mode/lisp/ol-bbdb hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-bbdb
/w/org-mode/lisp/ox-ascii hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-ascii
/w/org-mode/lisp/ob-python hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-python
/w/org-mode/lisp/ob-ref hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-ref
/w/org-mode/lisp/ob-js hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-js
/w/org-mode/lisp/ox-md hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-md
/w/org-mode/lisp/oc hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc
/w/org-mode/lisp/org-keys hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-keys
/w/org-mode/lisp/org-feed hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-feed
/w/org-mode/lisp/org-capture hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-capture
/w/org-mode/lisp/org-ctags hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-ctags
/w/org-mode/lisp/ob-lob hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-lob
/w/org-mode/lisp/ob-forth hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-forth
/w/org-mode/lisp/ob-clojure hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-clojure
/w/org-mode/lisp/ob-sass hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-sass
/w/org-mode/lisp/ol-eshell hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-eshell
/w/org-mode/lisp/org-timer hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-timer
/w/org-mode/lisp/ob-R hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-R
/w/org-mode/lisp/org-src hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-src
/w/org-mode/lisp/ox-koma-letter hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-koma-letter
/w/org-mode/lisp/ob-tangle hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-tangle
/w/org-mode/lisp/ob-matlab hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-matlab
/w/org-mode/lisp/org-macro hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-macro
/w/org-mode/lisp/ob-makefile hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-makefile
/w/org-mode/lisp/ox-texinfo hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-texinfo
/w/org-mode/lisp/ob-org hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-org
/w/org-mode/lisp/ol-docview hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-docview
/w/org-mode/lisp/org-list hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-list
/w/org-mode/lisp/ob-eval hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-eval
/w/org-mode/lisp/org-element hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-element
/w/org-mode/lisp/ob hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob
/w/org-mode/lisp/ob-sqlite hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-sqlite
/w/org-mode/lisp/org-clock hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-clock
/w/org-mode/lisp/org-compat hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-compat
/w/org-mode/lisp/org-mobile hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-mobile
/w/org-mode/lisp/ol hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol
/w/org-mode/lisp/ob-groovy hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-groovy
/w/org-mode/lisp/org-goto hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-goto
/w/org-mode/lisp/ob-emacs-lisp hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-emacs-lisp
/w/org-mode/lisp/ol-eww hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-eww
/w/org-mode/lisp/org-tempo hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-tempo
/w/org-mode/lisp/oc-csl hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc-csl
/w/org-mode/lisp/ob-ruby hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-ruby
/w/org-mode/lisp/org-crypt hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-crypt
/w/org-mode/lisp/ol-irc hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-irc
/w/org-mode/lisp/org-faces hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-faces
/w/org-mode/lisp/ob-latex hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-latex
/w/org-mode/lisp/org-colview hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-colview
/w/org-mode/lisp/ol-bibtex hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-bibtex
/w/org-mode/lisp/ob-lua hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-lua
/w/org-mode/lisp/org-protocol hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-protocol
/w/org-mode/lisp/org-attach-git hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-attach-git
/w/org-mode/lisp/ob-screen hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-screen
/w/org-mode/lisp/org-agenda hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-agenda
/w/org-mode/lisp/org-persist hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-persist
/w/org-mode/lisp/ob-sql hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-sql
/w/org-mode/lisp/ob-gnuplot hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-gnuplot
/w/org-mode/lisp/ob-sed hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-sed
/w/org-mode/lisp/ol-gnus hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-gnus
/w/org-mode/lisp/org-inlinetask hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-inlinetask
/w/org-mode/lisp/ox-html hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-html
/w/org-mode/lisp/oc-biblatex hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc-biblatex
/w/org-mode/lisp/org-pcomplete hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-pcomplete
/w/org-mode/lisp/ob-perl hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-perl
/w/org-mode/lisp/org-version hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-version
/w/org-mode/lisp/org-indent hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-indent
/w/org-mode/lisp/org-refile hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-refile
/w/org-mode/lisp/ob-julia hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-julia
/w/org-mode/lisp/ol-info hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-info
/w/org-mode/lisp/ol-doi hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-doi
/w/org-mode/lisp/org-habit hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-habit
/w/org-mode/lisp/org-entities hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-entities
/w/org-mode/lisp/ox-publish hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-publish
/w/org-mode/lisp/org-duration hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-duration
/w/org-mode/lisp/org-element-ast hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-element-ast
/w/org-mode/lisp/ob-ditaa hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-ditaa
/w/org-mode/lisp/ob-dot hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-dot
/w/org-mode/lisp/ob-C hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-C
/w/org-mode/lisp/ox-org hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-org
/w/org-mode/lisp/ox-beamer hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-beamer
/w/org-mode/lisp/ob-fortran hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-fortran
/w/org-mode/lisp/ob-maxima hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-maxima
/w/org-mode/lisp/ob-eshell hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-eshell
/w/org-mode/lisp/ol-w3m hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ol-w3m
/w/org-mode/lisp/org-id hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-id
/w/org-mode/lisp/ox-odt hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox-odt
/w/org-mode/lisp/ob-java hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-java
/w/org-mode/lisp/ob-calc hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-calc
/w/org-mode/lisp/org-attach hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-attach
/w/org-mode/lisp/ob-ocaml hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-ocaml
/w/org-mode/lisp/oc-bibtex hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/oc-bibtex
/w/org-mode/lisp/ox hides /opt/dc/emacs/share/emacs/31.0.50/lisp/org/ox
/w/org-mode/lisp/ob-lisp hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/ob-lisp
/w/org-mode/lisp/org-macs hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/org/org-macs
/w/flim/sasl hides /opt/dc/emacs/share/emacs/31.0.50/lisp/net/sasl
/home/dc/.emacs.d/elpa/hierarchy-20190425.842/hierarchy hides
/opt/dc/emacs/share/emacs/31.0.50/lisp/emacs-lisp/hierarchy

Features:
(shadow emacsbug rng-xsd xsd-regexp rng-cmpct rng-nxml rng-valid
nxml-mode nxml-outln nxml-rap view
mhtml-mode js c-ts-common cc-mode cc-fonts cc-guess cc-menus cc-cmds
cc-styles cc-align cc-engine
cc-vars cc-defs ox-texinfo ox-odt rng-loc rng-uri rng-parse rng-match
rng-dt rng-util rng-pttrn
nxml-parse nxml-ns nxml-enc xmltok nxml-util ox-latex ox-icalendar
ox-html table ox-ascii ox-publish
ox make-mode eglot external-completion jsonrpc xref flymake python
project emmet-mode css-mode
sgml-mode facemenu imenu solar cal-dst holidays holiday-loaddefs
mule-util cal-iso org-agenda
w3m-form textsec uni-scripts idna-mapping ucs-normalize uni-confusable
textsec-check w3m-symbol
w3m-bookmark elmo-internal mel-q-ccl elmo-multi elmo-maildir
modb-standard wl-template wl-fldmgr
wl-score wl-demo wl-thread wl-action wl wl-draft wl-folder elmo-nntp
elmo-net elmo-cache elmo-map
elmo-dop ps-print ps-print-loaddefs lpr elmo-filter wl-summary
wl-refile wl-message wl-mime
mime-play filename mime-edit mime-setup mail-mime-setup semi-setup
smtp sasl sasl-anonymous
sasl-login sasl-plain wl-e21 wl-highlight invisible inv-23 elmo-mime
mmelmo-buffer mmelmo-imap
mmimap mmbuffer wl-address pldap wl-util wl-vars wl-version
modb-generic elmo-flag elmo-localdir
elmo elmo-signal elmo-msgdb modb modb-entity elmo-date eword-encode
mime-parse elmo-util elmo-vars
elmo-version misearch multi-isearch face-remap org-duration vc-hg ffap
helm-git-grep smerge-mode
help-fns radix-tree diff winner tramp-archive tramp-gvfs
xterm-keybinder xt-mouse term/rxvt
term/xterm xterm vc-mtn beancount oc-basic ol-eww eww url-queue mm-url
ol-rmail ol-mhe ol-irc
ol-info ol-gnus nnselect gnus-art mm-uu mml2015 mm-view mml-smime
smime gnutls dig gnus-sum shr
pixel-fill kinsoku url-file svg dom gnus-group gnus-undo gnus-start
gnus-dbus dbus gnus-cloud nnimap
nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range message
sendmail yank-media puny rfc822
mml mml-sec epa epg rfc6068 epg-config mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047
rfc2045 ietf-drums gmm-utils mailheader gnus-win gnus nnheader
gnus-util mail-utils range mm-util
mail-prsvr ol-docview ol-bibtex bibtex ol-bbdb ol-w3m ol-doi
org-link-doi dired-aux vc-git diff-mode
track-changes vc-dispatcher server hideshow quail rot13 git-link
skeleton bustrofedon
dired-filetype-face dired-tar gnus-dired dired-x mime-w3m mime-view
mime-conf calist semi-def mime
mmgeneric eword-decode mel path-util pces pces-e20 pces-20 mime-def
mcs-e20 mcs-20 mcharset std11
ccl pccl pccl-20 broken static luna alist apel-ver product w3m-lnum
w3m doc-view timezone w3m-hist
bookmark-w3m w3m-ems w3m-favicon w3m-image w3m-fb tab-line w3m-proc
w3m-util savehist tramp-cache
time-stamp tramp-sh recentf tree-widget em-term term ehelp esh-ext
esh-proc esh-opt esh-io esh-arg
esh-module esh-module-loaddefs esh-util zone-select jka-compr zone
binview calc calc-loaddefs
calc-macs hexl generic generic-x boxquote rect rainbow-delimiters
rainbow-mode color
magit-autorevert magit-git magit-base magit-section crm dash compat
autorevert fc flashcard-sm5
flashcard keywiz gamegrid tt-mode helm-mode helm-misc helm-elisp
helm-eval edebug helm-sys
helm-for-files helm-bookmark helm-adaptive helm-info bookmark fringe
helm-external helm-net xml
helm-files image-dired image-dired-tags image-dired-external
image-dired-util image-mode dired dnd
dired-loaddefs exif filenotify tramp trampver tramp-integration
files-x tramp-message tramp-compat
shell tramp-loaddefs helm-buffers helm-occur helm-tags helm-locate
helm-grep helm-regexp helm-utils
helm-help helm-types helm helm-global-bindings helm-easymenu helm-core
async-bytecomp helm-source
helm-multi-match helm-lib async helm-autoloads diary-lib
diary-loaddefs chuck-mode jdecomp arc-mode
archive-mode cus-edit cus-load projectile lisp-mnt ibuf-ext edmacro
kmacro use-package-bind-key
bind-key use-package-core rcirc parse-time iso8601 offlineimap hexrgb
yasnippet mailabbrev org-crypt
org-capture org-attach org-protocol org-clock cal-move org-inlinetask
org-superstar org-element
org-persist xdg avl-tree generator org-test ert-x ert pp ewoc debug
backtrace org-id org-refile
org-element-ast inline org ob ob-tangle ob-ref ob-lob ob-table ob-exp
org-macro org-src sh-script
smie treesit executable ob-comint org-pcomplete pcomplete org-list
org-footnote org-faces
org-entities time-date noutline outline ob-emacs-lisp ob-core ob-eval
org-cycle org-table ol
org-fold org-fold-core org-keys oc org-loaddefs thingatpt find-func
cal-menu calendar cal-loaddefs
org-version org-compat org-macs format-spec ibuf-macs ibuffer
ibuffer-loaddefs mb-depth comp
comp-cstr warnings comp-run comp-common rx advice mwheel easy-mmode
so-long longlines grep compile
text-property-search comint regexp-opt ansi-osc ansi-color ring
revbufs derived disp-table
hide-mode-line time image hl-line color-theme wid-edit reporter xclip
finder-inf elp
boxquote-autoloads calfw-autoloads calfw-gcal-autoloads
calfw-ical-autoloads calfw-org-autoloads
csv-mode-autoloads debbugs-autoloads emacsql-psql-autoloads
emacsql-autoloads emmet-mode-autoloads
feature-mode-autoloads git-link-autoloads gnuplot-autoloads
google-translate-autoloads
haskell-mode-autoloads cl-extra help-mode helm-sql-connect-autoloads
htmlize-autoloads
idle-org-agenda-autoloads jabber-autoloads fsm-autoloads
jdecomp-autoloads jedi-autoloads
jedi-core-autoloads jinja2-mode-autoloads json-reformat-autoloads
jsonian-autoloads magit-autoloads
pcase git-commit-autoloads magit-section-autoloads mingus-autoloads
libmpdee-autoloads
mmm-jinja2-autoloads mmm-mode-autoloads oauth2-autoloads
org-superstar-autoloads persist-autoloads
projectile-autoloads python-environment-autoloads
rcirc-color-autoloads srv-autoloads cl
terraform-mode-autoloads tmr-autoloads transient-autoloads
typescript-mode-autoloads
vimrc-mode-autoloads vue-html-mode-autoloads with-editor-autoloads
xclip-autoloads
xterm-keybinder-autoloads yasnippet-autoloads zone-nyan-autoloads info
tool-bar dash-autoloads
package browse-url url url-proxy url-privacy url-expand url-methods
url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio
eieio-core cl-macs icons password-cache json subr-x map byte-opt gv
bytecomp byte-compile url-vars
cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren electric
uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode tabulated-list replace newcomment text-mode
lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select mouse
jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice seq simple
cl-generic indonesian philippine cham
georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite emoji-zwj
charscript charprop case-table epa-hook jka-cmpr-hook help abbrev
obarray oclosure cl-preloaded
button loaddefs theme-loaddefs faces cus-face macroexp files window
text-properties overlay sha1 md5
base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads
inotify multi-tty make-network-process native-compile emacs)

Memory information:
((conses 16 3160052 412323) (symbols 48 62684 6) (strings 32 325028
29395) (string-bytes 1 16950772)
 (vectors 16 304225) (vector-slots 8 4727886 155782) (floats 8 1843 114209)
 (intervals 56 81227 1605) (buffers 984 212))





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: Acknowledgement (31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size)
       [not found] ` <handler.73022.B.172543028723315.ack@debbugs.gnu.org>
@ 2024-09-04  6:25   ` Daniel Clemente
  0 siblings, 0 replies; 35+ messages in thread
From: Daniel Clemente @ 2024-09-04  6:25 UTC (permalink / raw)
  To: 73022

> Configured using:
> […]
> --without-x 'CFLAGS=-g3 -O3''

I sent another build's information by mistake. The backtraces are
actually from a -O0 build, with this information:


In GNU Emacs 31.0.50 (build 3, x86_64-pc-linux-gnu) of 2024-09-01 built
 on sonn
Repository revision: 99a03ddb2d43d67577814b96e40ec069739b6421
Repository branch: master
System Description: Devuan GNU/Linux 5 (daedalus)

Configured using:
 'configure --prefix=/opt/dc/emacs-dev/ --with-tiff=no --without-tiff
 --without-libsystemd --without-dbus --with-mailutils --without-modules
 --with-native-compilation --with-x-toolkit=no --without-imagemagick
 --without-xft --without-harfbuzz --without-freetype --without-libotf
 --without-xwidgets --without-xpm --without-jpeg --without-gif
 --without-png --without-webp --without-rsvg --without-cairo --without-x
 --without-sound --enable-checking=yes,glyphs --enable-profiling
 'CFLAGS=-g3 -O0 ''





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-04  6:09 bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size Daniel Clemente
       [not found] ` <handler.73022.B.172543028723315.ack@debbugs.gnu.org>
@ 2024-09-04  7:28 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-04 12:21   ` Eli Zaretskii
  1 sibling, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-04  7:28 UTC (permalink / raw)
  To: Daniel Clemente, 73022

Sorry, my last mail went at the wrong address.  Reposting.

 > In particular, I found a case in which an assert fails because the
 > window row glyph memory is not contained in the frame row glyph
 > memory.
 >
 > It happens in a recent build (99a03ddb2d4) built without X support.
 > I'm running it in a urxvt terminal but it happens in xterm too. It
 > crashes both with and without glyph debug. This is not related to
 > garbage collection like bug 71289.
 >
 > To reproduce:
 > 1. Open emacs -Q
 > 2. Press C-x 2 to split the frame (top/bottom)
 > 3. Make the terminal very small (I slowly resize the X window that's
 > running urxvt, to the minimum size, 1 row and 2 columns in my case).
 > This shrinking process alone can produce the crash when the window is
 > around 5 lines high
 > 4. It always crashes in my case. If it doesn't, make the terminal
 > larger again, and repeat the resizing for some seconds until it
 > crashes
 >
 > Note that the C-x 2 is required. The problem doesn't happen with a
 > left/right split (C-x 3). But it happens after a C-x 3 C-x 2.

Kindly have a look at the fix I proposed here:

https://lists.gnu.org/archive/html/emacs-devel/2024-09/msg00054.html

If necessary, I can send you a patch.

Thanks, martin






^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-04  7:28 ` bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-04 12:21   ` Eli Zaretskii
  2024-09-04 13:23     ` Eli Zaretskii
  2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 2 replies; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-04 12:21 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Wed, 4 Sep 2024 09:28:47 +0200
> From:  martin rudalics via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> 
>  > To reproduce:
>  > 1. Open emacs -Q
>  > 2. Press C-x 2 to split the frame (top/bottom)
>  > 3. Make the terminal very small (I slowly resize the X window that's
>  > running urxvt, to the minimum size, 1 row and 2 columns in my case).
>  > This shrinking process alone can produce the crash when the window is
>  > around 5 lines high
>  > 4. It always crashes in my case. If it doesn't, make the terminal
>  > larger again, and repeat the resizing for some seconds until it
>  > crashes
>  >
>  > Note that the C-x 2 is required. The problem doesn't happen with a
>  > left/right split (C-x 3). But it happens after a C-x 3 C-x 2.
> 
> Kindly have a look at the fix I proposed here:
> 
> https://lists.gnu.org/archive/html/emacs-devel/2024-09/msg00054.html

Thanks, but could you tell how that change could have affected this
assertion violation?  AFAICT, adjust_frame_glyphs is not in the
backtrace, so how could moving code inside of it affect what happens
here?





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-04 12:21   ` Eli Zaretskii
@ 2024-09-04 13:23     ` Eli Zaretskii
  2024-09-05  8:18       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-04 13:23 UTC (permalink / raw)
  To: rudalics; +Cc: n142857, 73022

> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> Date: Wed, 04 Sep 2024 15:21:16 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> > Date: Wed, 4 Sep 2024 09:28:47 +0200
> > From:  martin rudalics via "Bug reports for GNU Emacs,
> >  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> > 
> >  > To reproduce:
> >  > 1. Open emacs -Q
> >  > 2. Press C-x 2 to split the frame (top/bottom)
> >  > 3. Make the terminal very small (I slowly resize the X window that's
> >  > running urxvt, to the minimum size, 1 row and 2 columns in my case).
> >  > This shrinking process alone can produce the crash when the window is
> >  > around 5 lines high
> >  > 4. It always crashes in my case. If it doesn't, make the terminal
> >  > larger again, and repeat the resizing for some seconds until it
> >  > crashes
> >  >
> >  > Note that the C-x 2 is required. The problem doesn't happen with a
> >  > left/right split (C-x 3). But it happens after a C-x 3 C-x 2.
> > 
> > Kindly have a look at the fix I proposed here:
> > 
> > https://lists.gnu.org/archive/html/emacs-devel/2024-09/msg00054.html
> 
> Thanks, but could you tell how that change could have affected this
> assertion violation?  AFAICT, adjust_frame_glyphs is not in the
> backtrace, so how could moving code inside of it affect what happens
> here?

In any case, I can cause the assertion violation even after making the
change you suggested above.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-04 12:21   ` Eli Zaretskii
  2024-09-04 13:23     ` Eli Zaretskii
@ 2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05  9:18       ` Eli Zaretskii
  2024-09-08 11:09       ` Daniel Clemente
  1 sibling, 2 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05  8:18 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > Thanks, but could you tell how that change could have affected this
 > assertion violation?

I attach the patch now, sorry for not doing it earlier.

IIUC we are talking about this assertion

	  eassert (frame_size_change_delayed (XFRAME (w->frame))
		   || glyph_row_slice_p (window_row, frame_row));

Right?  If so, then this violation might be caused by the fact that we
(1) did resize windows according to the new sizes but (2) did not update
the frame sizes accordingly.  Which seems to match one observation that
the assertion gets violated when we increase the terminal height after
making it very small and not before.

 > AFAICT, adjust_frame_glyphs is not in the
 > backtrace, so how could moving code inside of it affect what happens
 > here?

I don't understand what you mean here.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-04 13:23     ` Eli Zaretskii
@ 2024-09-05  8:18       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05  9:19         ` Eli Zaretskii
  2024-09-08 11:07         ` Daniel Clemente
  0 siblings, 2 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05  8:18 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > In any case, I can cause the assertion violation even after making the
 > change you suggested above.

Following the OP's recipe I now get

#0  terminate_due_to_signal (sig=6, backtrace_limit=40) at ../../src/emacs.c:432
#1  0x000000000061b51b in emacs_abort () at ../../src/sysdep.c:2391
#2  0x0000000000541fc2 in cmcheckmagic (tty=0x1ebe0d0) at ../../src/cm.c:122
#3  0x0000000000546564 in tty_write_glyphs (f=0x1e7bb30, string=0x1e9afe0, len=80) at ../../src/term.c:819
#4  0x00000000005508c9 in write_glyphs (f=0x1e7bb30, string=0x1e9a0e0, len=80) at ../../src/terminal.c:164
#5  0x000000000042a6d7 in update_frame_line (f=0x1e7bb30, vpos=4, updating_menu_p=false) at ../../src/dispnew.c:5326
#6  0x00000000004298c5 in update_frame_1 (f=0x1e7bb30, force_p=true, inhibit_id_p=false, set_cursor_p=true, updating_menu_p=false) at ../../src/dispnew.c:5008
#7  0x000000000042514e in update_frame (f=0x1e7bb30, force_p=true, inhibit_hairy_id_p=false) at ../../src/dispnew.c:3346
#8  0x000000000047f556 in redisplay_internal () at ../../src/xdisp.c:17566
#9  0x00000000004800c7 in redisplay_preserve_echo_area (from_where=11) at ../../src/xdisp.c:17849
#10 0x0000000000740b5a in wait_reading_process_output (time_limit=30, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=XIL(0), wait_proc=0x0, just_wait_proc=0) at ../../src/process.c:5583
#11 0x000000000042df55 in sit_for (timeout=make_fixnum(30), reading=true, display_option=1) at ../../src/dispnew.c:6335
#12 0x00000000005f1523 in read_char (commandflag=1, map=XIL(0x7f59e8999aa3), prev_event=XIL(0), used_mouse_menu=0x7ffe2d75980f, end_time=0x0) at ../../src/keyboard.c:2926
#13 0x0000000000604743 in read_key_sequence (keybuf=0x7ffe2d7599c0, prompt=XIL(0), dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false, disable_text_conversion_p=false) at ../../src/keyboard.c:10747
#14 0x00000000005ecddb in command_loop_1 () at ../../src/keyboard.c:1424
#15 0x00000000006cb57b in internal_condition_case (bfun=0x5ec9ac <command_loop_1>, handlers=XIL(0x90), hfun=0x5ebe2e <cmd_error>) at ../../src/eval.c:1598
#16 0x00000000005ec573 in command_loop_2 (handlers=XIL(0x90)) at ../../src/keyboard.c:1163
#17 0x00000000006ca9d1 in internal_catch (tag=XIL(0x12360), func=0x5ec549 <command_loop_2>, arg=XIL(0x90)) at ../../src/eval.c:1277
#18 0x00000000005ec505 in command_loop () at ../../src/keyboard.c:1141
#19 0x00000000005eb8d0 in recursive_edit_1 () at ../../src/keyboard.c:749
#20 0x00000000005ebafc in Frecursive_edit () at ../../src/keyboard.c:832
#21 0x00000000005e7382 in main (argc=3, argv=0x7ffe2d759ff8) at ../../src/emacs.c:2624

Lisp Backtrace:
"redisplay_internal (C function)" (0x0)

so the original assertion violation is gone here.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05  9:18       ` Eli Zaretskii
  2024-09-05 14:45         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-08 11:09       ` Daniel Clemente
  1 sibling, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05  9:18 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 10:18:35 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  > Thanks, but could you tell how that change could have affected this
>  > assertion violation?
> 
> I attach the patch now, sorry for not doing it earlier.

You didn't attach it, but I think I understood what you wanted to
change, and did that by hand.

> IIUC we are talking about this assertion
> 
> 	  eassert (frame_size_change_delayed (XFRAME (w->frame))
> 		   || glyph_row_slice_p (window_row, frame_row));
> 
> Right?

Yes.

> If so, then this violation might be caused by the fact that we
> (1) did resize windows according to the new sizes but (2) did not update
> the frame sizes accordingly.

Can you elaborate on how this could be possible?  I always thought we
first allocate the frame matrices, and then the window matrices (by
suballocating them from the frame matrices).  Am I mistaken?

>  > AFAICT, adjust_frame_glyphs is not in the
>  > backtrace, so how could moving code inside of it affect what happens
>  > here?
> 
> I don't understand what you mean here.

Moving code in adjust_frame_glyphs could affect the assertion if the
assertion was being hit while adjust_frame_glyphs is still being
executed.  But that is not the case, so I don't understand how moving
some code in adjust_frame_glyphs without changing it could affect the
assertion violation.  I'm probably missing something.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  8:18       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05  9:19         ` Eli Zaretskii
  2024-09-05 14:46           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-08 11:07         ` Daniel Clemente
  1 sibling, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05  9:19 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 10:18:52 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  > In any case, I can cause the assertion violation even after making the
>  > change you suggested above.
> 
> Following the OP's recipe I now get
> 
> #0  terminate_due_to_signal (sig=6, backtrace_limit=40) at ../../src/emacs.c:432
> #1  0x000000000061b51b in emacs_abort () at ../../src/sysdep.c:2391
> #2  0x0000000000541fc2 in cmcheckmagic (tty=0x1ebe0d0) at ../../src/cm.c:122
> #3  0x0000000000546564 in tty_write_glyphs (f=0x1e7bb30, string=0x1e9afe0, len=80) at ../../src/term.c:819
> #4  0x00000000005508c9 in write_glyphs (f=0x1e7bb30, string=0x1e9a0e0, len=80) at ../../src/terminal.c:164

Are you running the latest codebase?  The assertions in cmcheckmagic
are supposed to be fixed there.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  9:18       ` Eli Zaretskii
@ 2024-09-05 14:45         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 15:10           ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 14:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 >> If so, then this violation might be caused by the fact that we
 >> (1) did resize windows according to the new sizes but (2) did not update
 >> the frame sizes accordingly.
 >
 > Can you elaborate on how this could be possible?  I always thought we
 > first allocate the frame matrices, and then the window matrices (by
 > suballocating them from the frame matrices).  Am I mistaken?

But if glyph_row_slice_p (window_row, frame_row) fails, something else
must have invalidated that.  I made that change here more than three
years ago and I can neither remember whether an assertion violation made
me do it or a crash nor why I did chose a term like "congruent" in the
comment.

One possibility I cannot exclude is that adjust_frame_size tries to
resize windows, that step (silently) fails in window_resize_check, the
old values stay in place but the new frame sizes are applied by
adjust_frame_size.  But precisely this scenario cannot be healed by my
patch so it's unlikely that it was the cause for the problem I
experienced back then.

 > Moving code in adjust_frame_glyphs could affect the assertion if the
 > assertion was being hit while adjust_frame_glyphs is still being
 > executed.  But that is not the case, so I don't understand how moving
 > some code in adjust_frame_glyphs without changing it could affect the
 > assertion violation.  I'm probably missing something.

I'm still too dense to understand what "Moving code" and "moving some
code" could mean in this context.  If you have enough patience left,
please elaborate.

Thanks, martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  9:19         ` Eli Zaretskii
@ 2024-09-05 14:46           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 14:58             ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 14:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > Are you running the latest codebase?  The assertions in cmcheckmagic
 > are supposed to be fixed there.

I suppose you mean the changes related to Bug#71289.  They should be
here with the last one as

commit 6fbb699bee2f54d65fbe6074735d42bbc0868c2c
Author: Eli Zaretskii <eliz@gnu.org>
Date:   Wed Jun 5 19:32:17 2024 +0300

     ; Fix last change.

Anyway, I pulled master again today, built with gtk3 and without-x and
both exhibit the same behavior with

MagicWrap (tty) == true
curY (tty) == 4
FrameRows (tty) == 5

in cmcheckmagic after shrinking the TTY window with the mouse to less
than two lines, slowly re-expanding it, at the time the split windows
would have to be redisplayed because the frame apparently became large
enough again.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 14:46           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 14:58             ` Eli Zaretskii
  2024-09-05 15:48               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05 14:58 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 16:46:15 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
> Anyway, I pulled master again today, built with gtk3 and without-x and
> both exhibit the same behavior with
> 
> MagicWrap (tty) == true
> curY (tty) == 4
> FrameRows (tty) == 5
> 
> in cmcheckmagic after shrinking the TTY window with the mouse to less
> than two lines, slowly re-expanding it, at the time the split windows
> would have to be redisplayed because the frame apparently became large
> enough again.

Please describe the recipe in more detail, starting from "emacs -Q -nw".





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 14:45         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 15:10           ` Eli Zaretskii
  2024-09-05 16:27             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-08 11:08             ` Daniel Clemente
  0 siblings, 2 replies; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05 15:10 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 16:45:52 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  >> If so, then this violation might be caused by the fact that we
>  >> (1) did resize windows according to the new sizes but (2) did not update
>  >> the frame sizes accordingly.
>  >
>  > Can you elaborate on how this could be possible?  I always thought we
>  > first allocate the frame matrices, and then the window matrices (by
>  > suballocating them from the frame matrices).  Am I mistaken?
> 
> But if glyph_row_slice_p (window_row, frame_row) fails, something else
> must have invalidated that.  I made that change here more than three
> years ago and I can neither remember whether an assertion violation made
> me do it or a crash nor why I did chose a term like "congruent" in the
> comment.

I agree with the theory that the frame matrices were reallocated
whereas the window matrices weren't, or the other way around.  I just
don't understand how it could have happened, given the code we have.

I noticed that causing this assertion to fail is not very easy.  For
example, if I drag the terminal emulator window one line at a time, I
can never cause it, even if I get to frame sizes that are much smaller
than the minimum we need for 2 windows.  Somehow, I need to drag the
frame so it resizes by several lines and/or columns.  Not sure why.

> One possibility I cannot exclude is that adjust_frame_size tries to
> resize windows, that step (silently) fails in window_resize_check, the
> old values stay in place but the new frame sizes are applied by
> adjust_frame_size.  But precisely this scenario cannot be healed by my
> patch so it's unlikely that it was the cause for the problem I
> experienced back then.

What is supposed to happen, with the current code, when the frame is
resized to less than the minimum dimensions we allow?  Shouldn't we
disallow/refuse such resizes?  And if we don't refuse, what will
happen to the windows?  E.g., if the frame is not tall enough to show
the menu bar, the two mode lines, the mini-window, and at least one
line for each of the two windows, what should I expect to see on
display?

>  > Moving code in adjust_frame_glyphs could affect the assertion if the
>  > assertion was being hit while adjust_frame_glyphs is still being
>  > executed.  But that is not the case, so I don't understand how moving
>  > some code in adjust_frame_glyphs without changing it could affect the
>  > assertion violation.  I'm probably missing something.
> 
> I'm still too dense to understand what "Moving code" and "moving some
> code" could mean in this context.  If you have enough patience left,
> please elaborate.

Taking some code and moving it to another place in the same function
can only affect what's going on in that function and the functions it
calls.  For example, if you had

   foo ();
   bar ();
   baz ();

and then you move the call to baz to be before the call to bar, like
this:

   foo ();
   baz ();
   bar ();

then I can understand why bar and its subroutines are affected.  But
once we are done with this code, all the 3 calls have been made, and
the order in which they were made can hardly matter for the code which
runs after that, right?

So if the crash was inside the call to bar, then I could understand
how moving the call to baz before it could affect the crash.  But the
backtrace from the assertion violation didn't show adjust_frame_glyphs
anywhere on the call-stack, so I don't understand how simply
rearranging code inside adjust_frame_glyphs could change something
_outside_ it.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 14:58             ` Eli Zaretskii
@ 2024-09-05 15:48               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 16:05                 ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 15:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

[-- Attachment #1: Type: text/plain, Size: 520 bytes --]

I attach four screenshots to illustrate what I'm doing.

First I split the window via C-x 2 (tty_1.png).  Now, using the mouse,
I drag the lower edge of the terminal window up in order to shrink that
window (tty_2.png).  At some moment the edge can't be dragged any more
(tty_3.png).  Now I drag the edge down to enlarge the window again
(tty_4.png).  When at this moment I drag the edge once more down Emacs
crashes.  Which IIUC means that Emacs crashes at the time it wants to
show the minibuffer window again.

martin

[-- Attachment #2: tty_4.png --]
[-- Type: image/png, Size: 25074 bytes --]

[-- Attachment #3: tty_3.png --]
[-- Type: image/png, Size: 14472 bytes --]

[-- Attachment #4: tty_2.png --]
[-- Type: image/png, Size: 26229 bytes --]

[-- Attachment #5: tty_1.png --]
[-- Type: image/png, Size: 47159 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 15:48               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 16:05                 ` Eli Zaretskii
  2024-09-05 16:30                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05 16:05 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 17:48:51 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
> I attach four screenshots to illustrate what I'm doing.
> 
> First I split the window via C-x 2 (tty_1.png).  Now, using the mouse,
> I drag the lower edge of the terminal window up in order to shrink that
> window (tty_2.png).  At some moment the edge can't be dragged any more
> (tty_3.png).  Now I drag the edge down to enlarge the window again
> (tty_4.png).  When at this moment I drag the edge once more down Emacs
> crashes.  Which IIUC means that Emacs crashes at the time it wants to
> show the minibuffer window again.

It doesn't crash for me when I repeat these steps, but I'm doing this
in PuTTY logged into a remote GNU/Linux system, so maybe that's the
reason.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 15:10           ` Eli Zaretskii
@ 2024-09-05 16:27             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-08 11:08             ` Daniel Clemente
  1 sibling, 0 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 16:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > What is supposed to happen, with the current code, when the frame is
 > resized to less than the minimum dimensions we allow?  Shouldn't we
 > disallow/refuse such resizes?  And if we don't refuse, what will
 > happen to the windows?  E.g., if the frame is not tall enough to show
 > the menu bar, the two mode lines, the mini-window, and at least one
 > line for each of the two windows, what should I expect to see on
 > display?

As for GUI frames I wrote some code to handle that but you didn't like
it back then.  Basically, we should do the following:

- Add min-size-hints so the window manage never tries to make the frame
   to small.  These have to correspond to the current window layout and
   the window decorations - a frame with split windows has a larger
   minimum size than one with one window only as we can see in the
   present thread.

- When the window manager doesn't comply, simple ignore the shrink
   request.  Portions of our frame that don't fit will be clipped by the
   window manager.  I wrote some code to always keep the minibuffer
   window visible in such case but cannot remember whether it works well.
   My WM (and Windows too) never tried to make a GUI frame smaller than I
   wanted.

On terminal emulators we should (or even do) conceptually the same as
with a non-compliant WM.  The terminal emulator has to do the clipping
just like the WM.

 > Taking some code and moving it to another place in the same function
 > can only affect what's going on in that function and the functions it
 > calls.  For example, if you had
 >
 >     foo ();
 >     bar ();
 >     baz ();
 >
 > and then you move the call to baz to be before the call to bar, like
 > this:
 >
 >     foo ();
 >     baz ();
 >     bar ();
 >
 > then I can understand why bar and its subroutines are affected.  But
 > once we are done with this code, all the 3 calls have been made, and
 > the order in which they were made can hardly matter for the code which
 > runs after that, right?

So I moved the assignments within adjust_frame_size (baz) in front of
the resize_frame_windows (bar) calls.  Is it that what you mean?

 > So if the crash was inside the call to bar, then I could understand
 > how moving the call to baz before it could affect the crash.  But the
 > backtrace from the assertion violation didn't show adjust_frame_glyphs
 > anywhere on the call-stack, so I don't understand how simply
 > rearranging code inside adjust_frame_glyphs could change something
 > _outside_ it.

Do you mean adjust_frame_size instead of adjust_frame_glyphs here so the
fact that makes you wonder is that adjust_frame_size never shows up in
the backtraces?

I could imagine that resize_frame_windows (or even
'window--pixel-to-total') mess up things in a way that confuses frame
based redisplay later.  In adjust_frame_glyphs_for_frame_redisplay we do

       eassert (matrix_dim.width == FRAME_TOTAL_COLS (f)
	       && matrix_dim.height == FRAME_TOTAL_LINES (f));

and I wonder whether there's an execution path that could bypass that
assertion.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 16:05                 ` Eli Zaretskii
@ 2024-09-05 16:30                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 16:58                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 18:15                     ` Eli Zaretskii
  0 siblings, 2 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 16:30 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > It doesn't crash for me when I repeat these steps, but I'm doing this
 > in PuTTY logged into a remote GNU/Linux system, so maybe that's the
 > reason.

Can you get the window as small as in my third screenshot?  In which
order does it re-show windows when you re-enlarge the window?  From top
to bottom with the minibuffer window last?

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 16:30                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 16:58                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 18:41                       ` Eli Zaretskii
  2024-09-05 18:15                     ` Eli Zaretskii
  1 sibling, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-05 16:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

One detail: If looking at the fourth, final screenshot I sent earlier,
then I notice that the last character of the lower mode line is black
which seems to correspond to curX (tty) == FrameCols (tty).  Does this
mean that the cursor is on the mode line of the lower normal window?

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 16:30                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05 16:58                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 18:15                     ` Eli Zaretskii
  1 sibling, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05 18:15 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 18:30:29 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  > It doesn't crash for me when I repeat these steps, but I'm doing this
>  > in PuTTY logged into a remote GNU/Linux system, so maybe that's the
>  > reason.
> 
> Can you get the window as small as in my third screenshot?

Yes.

> In which order does it re-show windows when you re-enlarge the
> window?  From top to bottom with the minibuffer window last?

First I see just empty frame, even when I enlarge the frame to 4
lines.  Then I see both windows, including the menu bar and the
mini-window.

Sometimes I see different behavior: first just a mode line of the
upper window with one text line, and 1 or 2 empty lines below the mode
line; then menu bar, and finally the bottom window with its mode line
and the mini-window.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 16:58                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-05 18:41                       ` Eli Zaretskii
  0 siblings, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-05 18:41 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Thu, 5 Sep 2024 18:58:47 +0200
> From: martin rudalics <rudalics@gmx.at>
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> 
> One detail: If looking at the fourth, final screenshot I sent earlier,
> then I notice that the last character of the lower mode line is black
> which seems to correspond to curX (tty) == FrameCols (tty).  Does this
> mean that the cursor is on the mode line of the lower normal window?

Probably.  But the best way of figuring this out is to look at the
cursor coordinates in the debugger.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  8:18       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05  9:19         ` Eli Zaretskii
@ 2024-09-08 11:07         ` Daniel Clemente
  2024-09-08 14:36           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 35+ messages in thread
From: Daniel Clemente @ 2024-09-08 11:07 UTC (permalink / raw)
  To: martin rudalics; +Cc: 73022, Eli Zaretskii

> #0  terminate_due_to_signal (sig=6, backtrace_limit=40) at ../../src/emacs.c:432
> #1  0x000000000061b51b in emacs_abort () at ../../src/sysdep.c:2391
> #2  0x0000000000541fc2 in cmcheckmagic (tty=0x1ebe0d0) at ../../src/cm.c:122
> #3  0x0000000000546564 in tty_write_glyphs (f=0x1e7bb30, string=0x1e9afe0, len=80) at ../../src/term.c:819
> #4  0x00000000005508c9 in write_glyphs (f=0x1e7bb30, string=0x1e9a0e0, len=80) at ../../src/terminal.c:164
> #5  0x000000000042a6d7 in update_frame_line (f=0x1e7bb30, vpos=4, updating_menu_p=false) at ../../src/dispnew.c:5326
> #6  0x00000000004298c5 in update_frame_1 (f=0x1e7bb30, force_p=true, inhibit_id_p=false, set_cursor_p=true,
> […]
> so the original assertion violation is gone here.
>

We're dealing with two type of assertion violations / crashes / backtraces:
- in update_frame_line, that causes chcheckmagic to fail
- in build_frame_matrix_from_leaf_window, assertion violation

With the same build I mentioned in the top post (that is, without any
code change), I can see both, after following the same instructions I
posted.
The update_frame_line happens much more frequently, therefore I
thought that the update_frame_line was fixed in 71289; but it's not: I
just reproduced the update_frame_line issue.

So you can't be sure that the original assertion violation is gone.
Your build may have crashed with the update_frame_line crash, before
reaching the build_frame_matrix_from_leaf_window crash.
The best would be to solve both crashes :-)

I don't know whether both crashes are related.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05 15:10           ` Eli Zaretskii
  2024-09-05 16:27             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-08 11:08             ` Daniel Clemente
  2024-09-08 11:31               ` Eli Zaretskii
  2024-09-08 14:58               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 2 replies; 35+ messages in thread
From: Daniel Clemente @ 2024-09-08 11:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: martin rudalics, 73022

> I noticed that causing this assertion to fail is not very easy.  For
> example, if I drag the terminal emulator window one line at a time, I
> can never cause it, even if I get to frame sizes that are much smaller
> than the minimum we need for 2 windows.  Somehow, I need to drag the
> frame so it resizes by several lines and/or columns.  Not sure why.
>

I can cause the build_frame_matrix_from_leaf_window failed assertion (
  glyph_row_slice_p(window_row, frame_row) is false  ) when slowly
resizing row by row (7→6→5 rows). The number of columns doesn't matter
(can be a normal one).

You can also try maximizing/unmaximizing“the window if you window
manager supports it. That's a way of suddenly changing the number of
rows from a normal value (e.g. 20) to a dangerous value (e.g. 4).
After unmaximizing it immediately crashes (if you did the C-x 2
split).





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-05  9:18       ` Eli Zaretskii
@ 2024-09-08 11:09       ` Daniel Clemente
  2024-09-08 14:43         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 35+ messages in thread
From: Daniel Clemente @ 2024-09-08 11:09 UTC (permalink / raw)
  To: martin rudalics; +Cc: 73022, Eli Zaretskii

> I attach the patch now, sorry for not doing it earlier.
>

Please attach patches if I can help trying out things. I don't know
this code so I may break it if I change the low-level behavior. But I
can safely add many breakpoints and debug messages to research the
bugs.
Apparently we could use more assertions in other parts of the code, or
move the existing ones (under glyph debug) to catch the problem
earlier.

In cmcheckmagic we have:
      if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
          emacs_abort ();

Is this an assertion that needs to always hold? I have tried
copy-pasting it at the beginning of tty_write_glyphs and I found that
it fails continuously (e.g. it tests: 62 >= 63-1). Actually I used a
breakpoint instead of emacs_abort.
Are there useful places where I could trace that  the assertion holds
true?, earlier places than the current place.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 11:08             ` Daniel Clemente
@ 2024-09-08 11:31               ` Eli Zaretskii
  2024-09-08 14:58               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-08 11:31 UTC (permalink / raw)
  To: Daniel Clemente; +Cc: rudalics, 73022

> From: Daniel Clemente <n142857@gmail.com>
> Date: Sun, 8 Sep 2024 11:08:14 +0000
> Cc: martin rudalics <rudalics@gmx.at>, 73022@debbugs.gnu.org
> 
> > I noticed that causing this assertion to fail is not very easy.  For
> > example, if I drag the terminal emulator window one line at a time, I
> > can never cause it, even if I get to frame sizes that are much smaller
> > than the minimum we need for 2 windows.  Somehow, I need to drag the
> > frame so it resizes by several lines and/or columns.  Not sure why.
> >
> 
> I can cause the build_frame_matrix_from_leaf_window failed assertion (
>   glyph_row_slice_p(window_row, frame_row) is false  ) when slowly
> resizing row by row (7→6→5 rows). The number of columns doesn't matter
> (can be a normal one).

I cannot.  Slowly dragging the window never crashes.

> You can also try maximizing/unmaximizing“the window if you window
> manager supports it. That's a way of suddenly changing the number of
> rows from a normal value (e.g. 20) to a dangerous value (e.g. 4).
> After unmaximizing it immediately crashes (if you did the C-x 2
> split).

This also never crashes here.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 11:07         ` Daniel Clemente
@ 2024-09-08 14:36           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-08 14:36 UTC (permalink / raw)
  To: Daniel Clemente; +Cc: 73022, Eli Zaretskii

 > We're dealing with two type of assertion violations / crashes / backtraces:
 > - in update_frame_line, that causes chcheckmagic to fail
 > - in build_frame_matrix_from_leaf_window, assertion violation
 >
 > With the same build I mentioned in the top post (that is, without any
 > code change), I can see both, after following the same instructions I
 > posted.
 > The update_frame_line happens much more frequently, therefore I
 > thought that the update_frame_line was fixed in 71289; but it's not: I
 > just reproduced the update_frame_line issue.

Good to know.

 > So you can't be sure that the original assertion violation is gone.

Right.

 > Your build may have crashed with the update_frame_line crash, before
 > reaching the build_frame_matrix_from_leaf_window crash.

Right again.  But I think that with my initial patch, the likeliness of
the later has decreased.

 > The best would be to solve both crashes :-)
 >
 > I don't know whether both crashes are related.

They are both caused by shrinking the frame size to something Emacs
doesn't like.  Note the

       if (width > 5 && height > 2)

check in handle_window_change_signal and the

   /* Don't allow too small height of text-mode frames, or else cm.c
      might abort in cmcheckmagic.  */
   if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
     {
       int min_height = (FRAME_MENU_BAR_LINES (f)
			+ FRAME_TAB_BAR_LINES (f)
			+ FRAME_WANTS_MODELINE_P (f)
			+ 2);	/* one text line and one echo-area line */

       if (retval < min_height)
	retval = min_height;
     }

in frame_windows_min_size.  People always were aware of the problem but
with split windows these values are of no use.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 11:09       ` Daniel Clemente
@ 2024-09-08 14:43         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-08 15:32           ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-08 14:43 UTC (permalink / raw)
  To: Daniel Clemente; +Cc: 73022, Eli Zaretskii

 > In cmcheckmagic we have:
 >        if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
 >            emacs_abort ();
 >
 > Is this an assertion that needs to always hold?

I very strongly doubt so myself.  And strangely it's _always_ an
off-by-one error here just as you sketched below.

 > I have tried
 > copy-pasting it at the beginning of tty_write_glyphs and I found that
 > it fails continuously (e.g. it tests: 62 >= 63-1). Actually I used a
 > breakpoint instead of emacs_abort.
 > Are there useful places where I could trace that  the assertion holds
 > true?, earlier places than the current place.

I suppose in all those cases curX (tty) == FrameCols (tty) does not hold
so the assertion does not trigger.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 11:08             ` Daniel Clemente
  2024-09-08 11:31               ` Eli Zaretskii
@ 2024-09-08 14:58               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-10 17:43                 ` Daniel Clemente
  1 sibling, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-08 14:58 UTC (permalink / raw)
  To: Daniel Clemente, Eli Zaretskii; +Cc: 73022

[-- Attachment #1: Type: text/plain, Size: 1378 bytes --]

 > I can cause the build_frame_matrix_from_leaf_window failed assertion (
 >    glyph_row_slice_p(window_row, frame_row) is false  ) when slowly
 > resizing row by row (7→6→5 rows). The number of columns doesn't matter
 > (can be a normal one).
 >
 > You can also try maximizing/unmaximizing“the window if you window
 > manager supports it. That's a way of suddenly changing the number of
 > rows from a normal value (e.g. 20) to a dangerous value (e.g. 4).
 > After unmaximizing it immediately crashes (if you did the C-x 2
 > split).

Please try the attached diff (from my heavily edited copy of master, if
it doesn't apply cleanly, complain immediately rather than messing up
your Emacs).  It should fix two silly bugs in window.el that make a
frame's safe minimum size much too large and includes the fix I proposed
earlier here.

And it moves the assignment of FrameRows to handle_window_change_signal
in dispnew.c.  Doing it in adjust_frame_size was silly (as Gerd Möllmann
noticed earlier).  FrameRows should be the height of the tty which can
be smaller than the height of our frame.  Emacs is supposed to store it
but not to modify it according to our capabilities.

The patch does not fix the cmcheckmagic problem but makes it much less
likely to occur.  And redisplay of an insanely small tty window looks
much better here.

martin

[-- Attachment #2: terminal-resize.diff --]
[-- Type: text/x-patch, Size: 4145 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index f4226fa4428..e648ccb270a 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1692,9 +1692,10 @@ window--min-size-1
 		     0
 		   (window-min-pixel-height window)))
 	      (max (ceiling pixel-height char-size)
-		   (if (window--min-size-ignore-p window ignore)
-		       0
-		     window-min-height))))))))))
+		   (cond
+		    ((window--min-size-ignore-p window ignore) 0)
+		    ((window-minibuffer-p window) 1)
+		    (t window-min-height)))))))))))
 
 (defun window-sizable (window delta &optional horizontal ignore pixelwise)
   "Return DELTA if DELTA lines can be added to WINDOW.
@@ -1888,7 +1889,7 @@ frame-windows-min-size
 	 (mini (window-next-sibling root)))
     (+ (window-min-size root horizontal ignore pixelwise)
        (if (and mini (not horizontal))
-	   (window-min-size mini horizontal nil pixelwise)
+	   (window-min-size mini horizontal ignore pixelwise)
 	 0))))
 
 (defun window--max-delta-1 (window delta &optional horizontal ignore trail noup pixelwise)
diff --git a/src/dispnew.c b/src/dispnew.c
index 1a243079e46..8a57866d3ed 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -6054,6 +6054,11 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height,
       adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, new_width),
 			 FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_height), 5,
 			 pretend, Qchange_frame_size);
+      if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
+	{
+	  FrameRows (FRAME_TTY (f)) = new_height;
+	  FrameCols (FRAME_TTY (f)) = new_width;
+	}
     }
 }
 
diff --git a/src/frame.c b/src/frame.c
index 7f4bf274ad9..9908ec307f7 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -827,14 +827,26 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
   new_text_lines = dos_new_text_lines - FRAME_TOP_MARGIN (f);
 #endif
 
+  /* Assign new sizes.  Do it here to make sure that frame based
+     redisplay gets congruent sizes for the dimensions of the frame
+     matrix and the combined window matrices.  */
+  FRAME_COLS (f) = new_text_cols;
+  FRAME_LINES (f) = new_text_lines;
+  FRAME_TEXT_WIDTH (f) = new_text_width;
+  FRAME_TEXT_HEIGHT (f) = new_text_height;
+  FRAME_PIXEL_WIDTH (f) = new_native_width;
+  FRAME_PIXEL_HEIGHT (f) = new_native_height;
+  FRAME_TOTAL_COLS (f) = FRAME_PIXEL_WIDTH (f) / FRAME_COLUMN_WIDTH (f);
+  FRAME_TOTAL_LINES (f) = FRAME_PIXEL_HEIGHT (f) / FRAME_LINE_HEIGHT (f);
+
   if (new_inner_width != old_inner_width)
     {
       resize_frame_windows (f, new_inner_width, true);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
 	 manipulating video hardware.  */
-      if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-	FrameCols (FRAME_TTY (f)) = new_text_cols;
+/**       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) **/
+/** 	FrameCols (FRAME_TTY (f)) = new_text_cols; **/
 
 #if defined (HAVE_WINDOW_SYSTEM)
       if (WINDOWP (f->tab_bar_window))
@@ -867,22 +879,12 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height,
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
 	 manipulating video hardware.  */
-      if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-	FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f);
+/**       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) **/
+/** 	FrameRows (FRAME_TTY (f)) = new_text_lines + FRAME_TOP_MARGIN (f); **/
     }
   else if (new_text_lines != old_text_lines)
     call2 (Qwindow__pixel_to_total, frame, Qnil);
 
-  /* Assign new sizes.  */
-  FRAME_COLS (f) = new_text_cols;
-  FRAME_LINES (f) = new_text_lines;
-  FRAME_TEXT_WIDTH (f) = new_text_width;
-  FRAME_TEXT_HEIGHT (f) = new_text_height;
-  FRAME_PIXEL_WIDTH (f) = new_native_width;
-  FRAME_PIXEL_HEIGHT (f) = new_native_height;
-  FRAME_TOTAL_COLS (f) = FRAME_PIXEL_WIDTH (f) / FRAME_COLUMN_WIDTH (f);
-  FRAME_TOTAL_LINES (f) = FRAME_PIXEL_HEIGHT (f) / FRAME_LINE_HEIGHT (f);
-
   {
     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
     int text_area_x, text_area_y, text_area_width, text_area_height;

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 14:43         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-08 15:32           ` Eli Zaretskii
  2024-09-08 17:01             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-08 15:32 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Sun, 8 Sep 2024 16:43:54 +0200
> Cc: Eli Zaretskii <eliz@gnu.org>, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  > In cmcheckmagic we have:
>  >        if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
>  >            emacs_abort ();
>  >
>  > Is this an assertion that needs to always hold?
> 
> I very strongly doubt so myself.  And strangely it's _always_ an
> off-by-one error here just as you sketched below.

I don't think it's an off-by-one.  It's simply that Emacs draws the
screen top to bottom, so the very first row that violates the
assertion by exceeding FrameRows is the only one that is seen.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 15:32           ` Eli Zaretskii
@ 2024-09-08 17:01             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-08 17:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 > I don't think it's an off-by-one.  It's simply that Emacs draws the
 > screen top to bottom, so the very first row that violates the
 > assertion by exceeding FrameRows is the only one that is seen.

You're right.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-08 14:58               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-10 17:43                 ` Daniel Clemente
  2024-09-11  8:07                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Daniel Clemente @ 2024-09-10 17:43 UTC (permalink / raw)
  To: martin rudalics; +Cc: 73022, Eli Zaretskii

> Please try the attached diff (from my heavily edited copy of master, if
> it doesn't apply cleanly, complain immediately rather than messing up
> your Emacs).  It should fix two silly bugs in window.el that make a
> frame's safe minimum size much too large and includes the fix I proposed
> earlier here.

It applies well; thanks.
By the way, (window-min-size) still answers 4 (with and without your patch).

Emacs feels a bit "stronger" in the C-x 2 scenario, meaning that it
survives shrinking+enlarging the terminal, but it still crashes
sometimes.
But it also crashes in a new situation: just by shrinking the
normal/initial/unsplit frame, i.e. without needing to do C-x 2. It
didn't crash before, so the patch doesn't make the whole Emacs more
stable yet.


Without doing C-x 2:

#4  0x00005555556c3016 in emacs_abort () at sysdep.c:2391
#5  0x000055555566d36f in cmcheckmagic (tty=0x55555608fa80) at cm.c:122
#6  0x0000555555671b1b in tty_write_glyphs (f=0x555556012ff0,
string=0x7ffff0f4ec10, len=80) at term.c:831
#7  0x000055555567c11d in write_glyphs (f=0x555556012ff0,
string=0x7ffff0f4dd10, len=80) at terminal.c:164
#8  0x0000555555591b60 in update_frame_line (f=0x555556012ff0, vpos=3,
updating_menu_p=false) at dispnew.c:5326

126          if (tty->termscript)
(gdb) p curY (tty)
$1 = 3
(gdb) p FrameRows (tty) - 1
$2 = 3
(gdb)


This one still happens (this is after C-x 2):
#5  0x000055555558b697 in build_frame_matrix_from_leaf_window
(frame_matrix=0x555556050420,
    w=0x555556013210) at dispnew.c:2647

>
> And it moves the assignment of FrameRows to handle_window_change_signal
> in dispnew.c.  Doing it in adjust_frame_size was silly (as Gerd Möllmann
> noticed earlier).  FrameRows should be the height of the tty which can
> be smaller than the height of our frame.  Emacs is supposed to store it
> but not to modify it according to our capabilities.
>

I don't have the expert opinion of how it should be. But I agree that
a source of the problem is that the tty can be smaller than the frame.
Frame and terminal may have different sizes and this creates
inconsistencies.

For instance, Eli recently added this code (dispnew.c):

  /* This should never happen, but evidently sometimes does if one
     resizes the frame quickly enough.  Prevent aborts in cmcheckmagic.  */
  if (vpos >= FRAME_TOTAL_LINES (f))
    return;

But this is checking the *frame*.  Later, the assertion in
cmcheckmagic will be made about the *terminal*.
I think the frame never gets smaller than 2 lines (there's code in
handle_window_change_signal to prevent it), but the tty can. So if
we're in a 1-line terminal, and updating the 2nd line, the above code
sees nothing wrong (the frame still has 2 lines) but cmcheckmagick
won't like it (the terminal doesn't have a 2nd line).
(Usual disclaimer: I don't know very well how this works. I'm often
brainstorming).

> And it moves the assignment of FrameRows to handle_window_change_signal
> in dispnew.c.

In practice, that code (in the new place you put it) is still inside an if: the
  if (width > 5 && height > 2)
in handle_window_change_signal. This means that in e.g. a 1-line
terminal, you won't be setting FrameRows to the actual number of lines
of terminal (1), as you wanted. It will still be the old value, e.g.
2, and it may make cmcheckmagic crash by trying to do things in line 2
(which exists in the frame, which has 2 lines) but not in the terminal
(which doesn't have a 2nd line).


One option seems to have FrameRows always match the amount of terminal
lines. Can we remove the "if (… height >2)" limitation, and allow
1-line, 2-line frames etc.? (To really match the terminal size). Other
changes may be needed in other places, to avoid working with very
small frames..

Otherwise, if we let FrameRows be larger than the amount of terminal
lines, another option could be:
At the beginning of tty_write_glyphs, check whether we've been asked
to write glyphs in a line which is higher than the amount of lines in
the terminal. If so, return without writing anything. (Because the
line would be invisible).
Or maybe in some of the callers of tty_write_glyphs. Don't call
tty_write_glyphs to write glyphs in a line which is not visible (it
exists in the frame, but doesn't exist in the terminal).


By the way, I saw that the cmcheckmagic code checks curY (tty) >=
FrameRows (tty) - 1, note the -1, whereas the dispnew.c code I quote
above doesn't use the -1. I hope this is ok. As mentioned they're
checking different things so it may be ok, though I don't understand
why the -1.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-10 17:43                 ` Daniel Clemente
@ 2024-09-11  8:07                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-11 12:22                     ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-11  8:07 UTC (permalink / raw)
  To: Daniel Clemente; +Cc: 73022, Eli Zaretskii

 > It applies well; thanks.
 > By the way, (window-min-size) still answers 4 (with and without your patch).

That's expected.  But (window-min-size (minibuffer-window)) should now
always evaluate to 1 and (frame-windows-min-size) should now give 5
instead of 8.  As for 'window-min-size' you can

- either (setq window-min-height 0) and then (window-min-size)

- or directly (window-min-size nil nil t)

which should both yield 2.  BTW, neither of the min size changes should
have any effect on the bug per se.  But it might cause it to occur
earlier or later and also in the one window case you mention below.

 > Emacs feels a bit "stronger" in the C-x 2 scenario, meaning that it
 > survives shrinking+enlarging the terminal, but it still crashes
 > sometimes.

Without the patch I could make it crash reliably.  I can't with it.

 > But it also crashes in a new situation: just by shrinking the
 > normal/initial/unsplit frame, i.e. without needing to do C-x 2. It
 > didn't crash before, so the patch doesn't make the whole Emacs more
 > stable yet.
 >
 >
 > Without doing C-x 2:
 >
 > #4  0x00005555556c3016 in emacs_abort () at sysdep.c:2391
 > #5  0x000055555566d36f in cmcheckmagic (tty=0x55555608fa80) at cm.c:122
 > #6  0x0000555555671b1b in tty_write_glyphs (f=0x555556012ff0,
 > string=0x7ffff0f4ec10, len=80) at term.c:831
 > #7  0x000055555567c11d in write_glyphs (f=0x555556012ff0,
 > string=0x7ffff0f4dd10, len=80) at terminal.c:164
 > #8  0x0000555555591b60 in update_frame_line (f=0x555556012ff0, vpos=3,
 > updating_menu_p=false) at dispnew.c:5326
 >
 > 126          if (tty->termscript)
 > (gdb) p curY (tty)
 > $1 = 3
 > (gdb) p FrameRows (tty) - 1
 > $2 = 3
 > (gdb)

Maybe because the frame can now get smaller after resize_frame_windows.
IIUC it all depends on where the cursor within the frame is.  In the
split window case you probably get crashes sooner if the cursor is in
the lower window.  Maybe still sooner if you resize the frame while the
minibuffer is active.  I didn't try such scenarios.

 > This one still happens (this is after C-x 2):
 > #5  0x000055555558b697 in build_frame_matrix_from_leaf_window
 > (frame_matrix=0x555556050420,
 >      w=0x555556013210) at dispnew.c:2647
 >
 >>
 >> And it moves the assignment of FrameRows to handle_window_change_signal
 >> in dispnew.c.  Doing it in adjust_frame_size was silly (as Gerd Möllmann
 >> noticed earlier).  FrameRows should be the height of the tty which can
 >> be smaller than the height of our frame.  Emacs is supposed to store it
 >> but not to modify it according to our capabilities.
 >>
 >
 > I don't have the expert opinion of how it should be. But I agree that
 > a source of the problem is that the tty can be smaller than the frame.
 > Frame and terminal may have different sizes and this creates
 > inconsistencies.

Indeed.  The GUI code doesn't have the cursor problem.  There an
arbitrarily large Emacs frame may continue to live within a tiny WM
window with an invisible cursor.

 > For instance, Eli recently added this code (dispnew.c):
 >
 >    /* This should never happen, but evidently sometimes does if one
 >       resizes the frame quickly enough.  Prevent aborts in cmcheckmagic.  */
 >    if (vpos >= FRAME_TOTAL_LINES (f))
 >      return;
 >
 > But this is checking the *frame*.  Later, the assertion in
 > cmcheckmagic will be made about the *terminal*.

Right.  This should probably be

   if (FRAME_TERMCAP_P (f) && vpos >= FrameRows (FRAME_TTY (f)))
     return;

And it's not about resizing frames "quickly".  Here I can crash it in a
very slow fashion too.

 > I think the frame never gets smaller than 2 lines (there's code in
 > handle_window_change_signal to prevent it), but the tty can. So if
 > we're in a 1-line terminal, and updating the 2nd line, the above code
 > sees nothing wrong (the frame still has 2 lines) but cmcheckmagick
 > won't like it (the terminal doesn't have a 2nd line).
 > (Usual disclaimer: I don't know very well how this works. I'm often
 > brainstorming).

Right.  But I can get cmcheckmagic crash here with a 20 lines frame too.

 >> And it moves the assignment of FrameRows to handle_window_change_signal
 >> in dispnew.c.
 >
 > In practice, that code (in the new place you put it) is still inside an if: the
 >    if (width > 5 && height > 2)
 > in handle_window_change_signal. This means that in e.g. a 1-line
 > terminal, you won't be setting FrameRows to the actual number of lines
 > of terminal (1), as you wanted. It will still be the old value, e.g.
 > 2, and it may make cmcheckmagic crash by trying to do things in line 2
 > (which exists in the frame, which has 2 lines) but not in the terminal
 > (which doesn't have a 2nd line).

The 5/2 checks cannot handle split windows.  These are artifacts from
the past.

 > One option seems to have FrameRows always match the amount of terminal
 > lines. Can we remove the "if (… height >2)" limitation, and allow
 > 1-line, 2-line frames etc.? (To really match the terminal size). Other
 > changes may be needed in other places, to avoid working with very
 > small frames..

We should do that.  In principle we should allow height and width to
become zero.  Who knows what today's terminals permit?

 > Otherwise, if we let FrameRows be larger than the amount of terminal
 > lines, another option could be:
 > At the beginning of tty_write_glyphs, check whether we've been asked
 > to write glyphs in a line which is higher than the amount of lines in
 > the terminal. If so, return without writing anything. (Because the
 > line would be invisible).
 > Or maybe in some of the callers of tty_write_glyphs. Don't call
 > tty_write_glyphs to write glyphs in a line which is not visible (it
 > exists in the frame, but doesn't exist in the terminal).

I think FrameRows should always reflect the size of the terminal as it
was reported to us.  If it doesn't, we'll never be able to trace changes
of the terminal size correctly.

 > By the way, I saw that the cmcheckmagic code checks curY (tty) >=
 > FrameRows (tty) - 1, note the -1, whereas the dispnew.c code I quote
 > above doesn't use the -1. I hope this is ok. As mentioned they're
 > checking different things so it may be ok, though I don't understand
 > why the -1.

The cmcheckmagic code is about a very peculiar situation that is hardly
relevant for today's terminals I think.  Here I can never crash a build
that doesn't check assertions.  Can you?

martin

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-11  8:07                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-11 12:22                     ` Eli Zaretskii
  2024-09-11 14:37                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-11 12:22 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Wed, 11 Sep 2024 10:07:21 +0200
> Cc: Eli Zaretskii <eliz@gnu.org>, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  > For instance, Eli recently added this code (dispnew.c):
>  >
>  >    /* This should never happen, but evidently sometimes does if one
>  >       resizes the frame quickly enough.  Prevent aborts in cmcheckmagic.  */
>  >    if (vpos >= FRAME_TOTAL_LINES (f))
>  >      return;
>  >
>  > But this is checking the *frame*.  Later, the assertion in
>  > cmcheckmagic will be made about the *terminal*.
> 
> Right.  This should probably be
> 
>    if (FRAME_TERMCAP_P (f) && vpos >= FrameRows (FRAME_TTY (f)))
>      return;

That code is in update_frame_line, which is used only for TTY frames
and uses frame glyph matrices.  IOW, it updates the entire frame as a
single large window.  In addition, on a TTY terminal there's only one
frame visible at any given time, and only that one frame is being
redrawn, ever.

Given the above, why is that code incorrect?

> And it's not about resizing frames "quickly".  Here I can crash it in a
> very slow fashion too.

Good for you, but my comment describes the situation in which I saw
that particular problem.  As I already said, I can never crash Emacs
if I resize the terminal emulator window slowly.

> The cmcheckmagic code is about a very peculiar situation that is hardly
> relevant for today's terminals I think.  Here I can never crash a build
> that doesn't check assertions.

Most probably because the terminal driver simply ignores such writes.
AFAIU, the assertion there is not because of the terminal, it is there
to catch Emacs bugs.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-11 12:22                     ` Eli Zaretskii
@ 2024-09-11 14:37                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-09-11 15:06                         ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-11 14:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 >>   > For instance, Eli recently added this code (dispnew.c):
 >>   >
 >>   >    /* This should never happen, but evidently sometimes does if one
 >>   >       resizes the frame quickly enough.  Prevent aborts in cmcheckmagic.  */
 >>   >    if (vpos >= FRAME_TOTAL_LINES (f))
 >>   >      return;
 >>   >
 >>   > But this is checking the *frame*.  Later, the assertion in
 >>   > cmcheckmagic will be made about the *terminal*.
 >>
 >> Right.  This should probably be
 >>
 >>     if (FRAME_TERMCAP_P (f) && vpos >= FrameRows (FRAME_TTY (f)))
 >>       return;
 >
 > That code is in update_frame_line, which is used only for TTY frames
 > and uses frame glyph matrices.  IOW, it updates the entire frame as a
 > single large window.  In addition, on a TTY terminal there's only one
 > frame visible at any given time, and only that one frame is being
 > redrawn, ever.
 >
 > Given the above, why is that code incorrect?

It _might_ be incorrect when we allow FRAME_TOTAL_LINES (f) to exceed
FrameRows (FRAME_TTY (f)) because we refuse to shrink a frame below some
height.  That's why I used the term "probably".  If I knew what that
code does in all consequences, I could tell you more.  But I don't know.

 >> And it's not about resizing frames "quickly".  Here I can crash it in a
 >> very slow fashion too.
 >
 > Good for you, but my comment describes the situation in which I saw
 > that particular problem.  As I already said, I can never crash Emacs
 > if I resize the terminal emulator window slowly.

And as I already said I can crash Emacs reliably if I slowly shrink the
window, slowly expand it again, precisely at the moment it should reshow
the minibuffer window.  You can ask me any question about the state of
the frame and its windows at the time of the crash.

 > Most probably because the terminal driver simply ignores such writes.
 > AFAIU, the assertion there is not because of the terminal, it is there
 > to catch Emacs bugs.

Then tell us how to catch it.  I'm already out of ideas.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-11 14:37                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-09-11 15:06                         ` Eli Zaretskii
  2024-09-12  9:49                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2024-09-11 15:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: n142857, 73022

> Date: Wed, 11 Sep 2024 16:37:58 +0200
> Cc: n142857@gmail.com, 73022@debbugs.gnu.org
> From: martin rudalics <rudalics@gmx.at>
> 
>  >>   > For instance, Eli recently added this code (dispnew.c):
>  >>   >
>  >>   >    /* This should never happen, but evidently sometimes does if one
>  >>   >       resizes the frame quickly enough.  Prevent aborts in cmcheckmagic.  */
>  >>   >    if (vpos >= FRAME_TOTAL_LINES (f))
>  >>   >      return;
>  >>   >
>  >>   > But this is checking the *frame*.  Later, the assertion in
>  >>   > cmcheckmagic will be made about the *terminal*.
>  >>
>  >> Right.  This should probably be
>  >>
>  >>     if (FRAME_TERMCAP_P (f) && vpos >= FrameRows (FRAME_TTY (f)))
>  >>       return;
>  >
>  > That code is in update_frame_line, which is used only for TTY frames
>  > and uses frame glyph matrices.  IOW, it updates the entire frame as a
>  > single large window.  In addition, on a TTY terminal there's only one
>  > frame visible at any given time, and only that one frame is being
>  > redrawn, ever.
>  >
>  > Given the above, why is that code incorrect?
> 
> It _might_ be incorrect when we allow FRAME_TOTAL_LINES (f) to exceed
> FrameRows (FRAME_TTY (f)) because we refuse to shrink a frame below some
> height.  That's why I used the term "probably".  If I knew what that
> code does in all consequences, I could tell you more.  But I don't know.

If FRAME_TOTAL_LINES is different from FrameRows at that spot, it's a
bug, isn't it?

The reason I didn't want to depend on FrameRows is that it might be
modified by a signal handler, and I couldn't convince myself that they
will always be in sync when we get to that spot.  FRAME_TOTAL_LINES is
the result of us adjusting the frame size when it's safe to do so, and
it sounded like a better idea to me.

>  >> And it's not about resizing frames "quickly".  Here I can crash it in a
>  >> very slow fashion too.
>  >
>  > Good for you, but my comment describes the situation in which I saw
>  > that particular problem.  As I already said, I can never crash Emacs
>  > if I resize the terminal emulator window slowly.
> 
> And as I already said I can crash Emacs reliably if I slowly shrink the
> window, slowly expand it again, precisely at the moment it should reshow
> the minibuffer window.  You can ask me any question about the state of
> the frame and its windows at the time of the crash.

I still don't understand what is supposed to happen when we shrink the
frame to less lines/columns than the minimum window dimensions we
allow.  Also, I'd be happier if you could describe the sequence of
events that lead to frame and window resizing following a SIGWINCH.

>  > Most probably because the terminal driver simply ignores such writes.
>  > AFAIU, the assertion there is not because of the terminal, it is there
>  > to catch Emacs bugs.
> 
> Then tell us how to catch it.  I'm already out of ideas.

Maybe later, when I have more time to think about this.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size
  2024-09-11 15:06                         ` Eli Zaretskii
@ 2024-09-12  9:49                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 35+ messages in thread
From: martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-12  9:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: n142857, 73022

 >> It _might_ be incorrect when we allow FRAME_TOTAL_LINES (f) to exceed
 >> FrameRows (FRAME_TTY (f)) because we refuse to shrink a frame below some
 >> height.  That's why I used the term "probably".  If I knew what that
 >> code does in all consequences, I could tell you more.  But I don't know.
 >
 > If FRAME_TOTAL_LINES is different from FrameRows at that spot, it's a
 > bug, isn't it?

It depends.  On a GUI frame do the following: In *scratch* insert the
two lines

(insert (format "%s" (frame-native-height)))
(insert (format "%s" (window-pixel-height (frame-root-window))))

and then do C-x 2 three times so yet get four windows.  Now with the
mouse drag the lower border upwards as far as you can.  The minibuffer
window should have disappeared by now.  Evaluate the two lines above by
putting point at their end and typing C-x e.  You will see that the
second value exceeds the first one - the root window got larger than
its frame.  So the window dimensions as Emacs can reasonably draw them
exceed the dimensions of the window as the WM gives them to us.

The same thing happens on TTY frames.  With split windows, the size of
the root window may exceed the size of the terminal window.  Whether we
now synch FRAME_TOTAL_LINES and FrameRows is just a matter of taste.

 > I still don't understand what is supposed to happen when we shrink the
 > frame to less lines/columns than the minimum window dimensions we
 > allow.

There are two minimum window dimensions we "allow": The first are the
hard-coded 5/2 values in handle_window_change_signal and additionally
imposed in frame_windows_min_size.  IIUC neither of these takes care of
menu or tab bars nor of any window splitting.  The second is the
'frame-windows-min-size' code that takes care of the entire frame layout
in an equal fashion for GUI frames and TTY frames.  In either case we do
not shrink the dimensions of our windows but keep them as in the GUI
example above.

 > Also, I'd be happier if you could describe the sequence of
 > events that lead to frame and window resizing following a SIGWINCH.

IIUC we call change_frame_size, possibly delay it, and eventually call
adjust_frame_size just as we do for GUI frames.  There's no special
magic involved.

The problematic thing I see is that the entire cursor wrapping code
including the check in cmcheckmagic seem botched because when a window
is virtually drawn below the border of the terminal window (as in the
GUI example sketched above) we do not check whether the cursor ends up
below that border too.  In particular the form

   /* First the degenerate case */
     if (row == curY (tty) && col == curX (tty)) /* already there */
     return;

in cmgoto seems to indicate that we leave the cursor at its current
location.  Maybe we do that even earlier, for example, in

   if (curY (tty) == vpos
       && curX (tty) == hpos)
     return;

of tty_cursor_to.  And maybe neither of these is relevant because
redisplay simply does nothing if the size of the root window does not
change (I wouldn't know where and how redisplay checks that).  At the
very end the check in cmcheckmagic aborts us in any such case.

martin





^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2024-09-12  9:49 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-04  6:09 bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size Daniel Clemente
     [not found] ` <handler.73022.B.172543028723315.ack@debbugs.gnu.org>
2024-09-04  6:25   ` bug#73022: Acknowledgement (31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size) Daniel Clemente
2024-09-04  7:28 ` bug#73022: 31.0.50; Crash in build_frame_matrix_from_leaf_window after C-x 2 and reducing terminal size martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-04 12:21   ` Eli Zaretskii
2024-09-04 13:23     ` Eli Zaretskii
2024-09-05  8:18       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05  9:19         ` Eli Zaretskii
2024-09-05 14:46           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05 14:58             ` Eli Zaretskii
2024-09-05 15:48               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05 16:05                 ` Eli Zaretskii
2024-09-05 16:30                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05 16:58                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05 18:41                       ` Eli Zaretskii
2024-09-05 18:15                     ` Eli Zaretskii
2024-09-08 11:07         ` Daniel Clemente
2024-09-08 14:36           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05  8:18     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05  9:18       ` Eli Zaretskii
2024-09-05 14:45         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-05 15:10           ` Eli Zaretskii
2024-09-05 16:27             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-08 11:08             ` Daniel Clemente
2024-09-08 11:31               ` Eli Zaretskii
2024-09-08 14:58               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-10 17:43                 ` Daniel Clemente
2024-09-11  8:07                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-11 12:22                     ` Eli Zaretskii
2024-09-11 14:37                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-11 15:06                         ` Eli Zaretskii
2024-09-12  9:49                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-08 11:09       ` Daniel Clemente
2024-09-08 14:43         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-09-08 15:32           ` Eli Zaretskii
2024-09-08 17:01             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).