[Bug 268076] dc(1): crash on window size change

From: <bugzilla-noreply_at_freebsd.org>
Date: Wed, 30 Nov 2022 16:04:49 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268076

--- Comment #4 from Marcin Cieślak <saper@saper.info> ---
Thank you for a very quick response, here is how it looks now:

dc(1) prints "ready for more input" every time I resize the window, but does
not crash at all

radziecki> ./bin/dc              
2 2 + p
4
ready for more input
5 # resize
ready for more input
ready for more input
ready for more input

bc(1) exists as before

radziecki> ./bin/bc
>>> 2 + 2 
4
>>> 
Fatal error: I/O error
    Function: (main)



This is your software and I fully respect your right to design its features as
you see fit, especially given the maintenance burden is mostly on you.

I think classic "perror()" would be slighly better here (of course without all
the i18n goodies).

diff --git a/src/history.c b/src/history.c
index bc15da5b..15e6e25b 100644
--- a/src/history.c
+++ b/src/history.c
@@ -264,8 +264,7 @@ bc_history_line(BcHistory* h, BcVec* vec, const char*
prompt)
                // If this is true, there was an error. Otherwise, it's just
EOF.
                if (len == -1)
                {
-                       if (errno == ENOMEM) bc_err(BC_ERR_FATAL_ALLOC_ERR);
-                       bc_err(BC_ERR_FATAL_IO_ERR);
+                       perror("reading next input line failed");
                }
                else
                {

Maybe it could be helpful to tell you how I approached the problem.
This is just my personal story and certainly not a case for everyone
approaching unknown software:

1. First I did 

git grep "Fatal error"

to find out there is i18n system in place and it looks like "I/O Error" is an
error number 5 (counted by hand in "bc_err_msgs")

2. Then I did

git grep bc_err_msgs

to learn that the whole i18n thing is initialized via bc_vm_defaultMsgs()
but still no clue regarding what might have caused it

3. Then tried my luck to

git grep bc_err_ids

that reveals there is bc_vm_handleError() and the name looks promising

4. Having learned that it was easier:

(gdb) b bc_vm_handleError
Breakpoint 1 at 0x2372f8: file ./src/vm.c, line 351.
(gdb) run
Starting program: /usr/home/saper/src/bc/bin/bc 
warning: Could not load shared library symbols for [vdso].
Do you need "set solib-search-path" or "set sysroot"?
>>> 
Breakpoint 1, bc_vm_handleError (e=BC_ERR_FATAL_IO_ERR, line=0) at
./src/vm.c:351
351             uchar id = bc_err_ids[e];
(gdb) bt
#0  bc_vm_handleError (e=BC_ERR_FATAL_IO_ERR, line=0)
    at ./src/vm.c:351
#1  0x0000000000218169 in bc_history_line (
    h=0x23e440 <vm_data+1584>, vec=0x23e228 <vm_data+1048>, 
    prompt=0x201ca5 ">>> ") at ./src/history.c:268
#2  0x0000000000234e10 in bc_read_line (
    vec=0x23e228 <vm_data+1048>, prompt=0x201ca5 ">>> ")
    at ./src/read.c:236
#3  0x000000000023827e in bc_vm_readLine (clear=true)
    at ./src/vm.c:1114
#4  0x000000000023ac20 in bc_vm_stdin () at ./src/vm.c:1165
#5  0x0000000000239b7d in bc_vm_exec () at ./src/vm.c:1501
#6  0x0000000000238eae in bc_vm_boot (argc=1, argv=0x7fffffffe6b0)
    at ./src/vm.c:1691
#7  0x000000000021131c in bc_main (argc=1, argv=0x7fffffffe6b0)
    at ./src/bc.c:62
#8  0x000000000021a199 in main (argc=1, argv=0x7fffffffe6b0)
    at ./src/main.c:108
(gdb) down
Bottom (innermost) frame selected; you cannot go down.
(gdb) up
#1  0x0000000000218169 in bc_history_line (h=0x23e440 <vm_data+1584>, 
    vec=0x23e228 <vm_data+1048>, prompt=0x201ca5 ">>> ")
    at ./src/history.c:268
268                             bc_err(BC_ERR_FATAL_IO_ERR);
(gdb) list -
263             {
264                     // If this is true, there was an error. Otherwise, it's
just EOF.
265                     if (len == -1)
266                     {
267                             if (errno == ENOMEM)
bc_err(BC_ERR_FATAL_ALLOC_ERR);
268                             bc_err(BC_ERR_FATAL_IO_ERR);
269                     }
270                     else
271                     {
272                             bc_file_printf(&vm->fout, "\n");
(gdb) 
253                             }
254                     }
255                     else bc_history_prompt = bc_vm_strdup(prompt);
256             }
257     
258             // Get the line.
259             line = el_gets(h->el, &len);
260     
261             // If there is no line...
262             if (BC_ERR(line == NULL))
(gdb) p line
$1 = 0x0
(gdb) p h->el
$2 = (EditLine *) 0x800a6a000
(gdb) p len
$3 = -1


What certainly would help is some unique identification of the position of the
error in the code (be it __FILE__, __LINE__ if need be). BC_ERR_FATAL_IO_ERR is
thrown in dozen or so places so I can't quickly tell where did it fail.

Since FreeBSD runs optimized binaries, but with debug symbols available, it was
frustrating to see all local variables optimized out, only errno was there:

(gdb) p len
$1 = <optimized out>
(gdb) p line
$2 = <optimized out>
(gdb) p h->el
value has been optimized out
(gdb) p errno
$3 = 4

(feel free to move this conversation somewhere else, sadly could not register
at https://git.yzena.com/gavin/bc/)

But again, thank you for building this software for us.

-- 
You are receiving this mail because:
You are the assignee for the bug.