unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
From: Thomas White <taw-gl@bitwiz.me.uk>
To: 55568@debbugs.gnu.org
Subject: bug#55568: Error in string->number when calling (backtrace) without COLUMNS envionment variable
Date: Sun, 22 May 2022 01:04:44 +0200	[thread overview]
Message-ID: <20220522010444.6bea02a1@dorian> (raw)

Summary:

This appears to be a combination of two separate problems:

1. Procedure terminal-width in system/repl/debug.scm does not
gracefully handle a #f return value from (getenv "COLUMNS").

2. The COLUMNS environment variable is only set when readline is
active, which never happens if a program is run directly via a command
line argument.

Relates to https://debbugs.gnu.org/cgi/bugreport.cgi?bug=36677
("Don't truncate backtraces").



Detailed report:

I want to set up an exception handler to get a backtrace when something
goes wrong in my program.  The simple test code below is based on the
example code found in
https://www.gnu.org/software/guile/manual/html_node/Pre_002dUnwind-Debugging.html

The output on Guile 3.0.7 is below.  Instead of a backtrace, the call
to the backtrace routine produces the following error:

system/repl/debug.scm:72:40: In procedure string->number: Wrong type
argument in position 1 (expecting string): #f

I've also tested on the latest Git version (3.0.8.13-cc455), with the
same result.

The line referred to in debug.scm (shown below) is all about
determining the width of the terminal based on the environment variable
COLUMNS.  When run as shown in the example below, this variable is not
set, causing string->number to fail.  This is the first problem, which
probably has a simple fix for someone who properly understands this
routine.  I might have time to look at this myself in a few weeks' time.

(define terminal-width
  (let ((set-width (make-fluid)))
    (case-lambda
      (()
       (or (fluid-ref set-width)
           (let ((w (false-if-exception (string->number (getenv "COLUMNS")))))
             (and (integer? w) (exact? w) (> w 0) w))
           72))
      ((w)
       (if (or (not w) (and (integer? w) (exact? w) (> w 0)))
           (fluid-set! set-width w)
           (error "Expected a column number (a positive integer)" w))))))

The second problem is the question of why COLUMNS is not set in the
first place.  The problem goes away after uncommenting the (setenv .. ) line in the
test case code, forcing it to be set when the backtrace is generated.

I think the problem is that COLUMNS is a shell variable, which is not
the same thing as an envionment variable.  Read here:
https://stackoverflow.com/questions/1780483/lines-and-columns-environmental-variables-lost-in-a-script

In a shell, COLUMNS is usually (not always!) available.  But because
it's not an environment variable, it doesn't get exported to Guile.
Within Guile, COLUMNS is only set after activate-readline is called.
Therefore, we get proper backtraces when the program is run from an
already-running REPL, like this:

$ guile
scheme@(guile-user)> (load "testcase.scm")
---> correct backtrace

But not when running the program directly, like this:

$ guile testcase.scm
---> string->number error instead of backtrace

This appears to be confirmed by testing with various combinations of
"guile -l" and adding/removing readline references from my ~/.guile file.

Fixing the first problem will work around the overall problem in a
reasonably acceptable way.  We would only have backtraces with the
correct width if readline is activated.  To get proper width backtraces
in all circumstances would require a different way of getting the
terminal width.

With thanks to stis on IRC this evening, who first realised what was
going on.




Test case code:

(use-modules (ice-9 threads)
             (ice-9 exceptions)
             (ice-9 control))

;; Uncomment the following line to work round the problem
;; (setenv "COLUMNS" "110") 

(define (do-test)
  (raise-exception
    (make-exception
      (make-exception-with-message "Test exception")
      (make-exception-with-irritants (list 1 2 3 4 5)))))

(define (call-with-backtrace thunk)
  (let/ec cancel
          (start-stack 'stack-with-backtrace
                       (with-exception-handler
                         (lambda (exn)
                           (display "Error occurred\n")
                           (backtrace)
                           (cancel #f))
                         thunk))))

(define (exception-test)
  (call-with-backtrace
    (lambda ()
      (sleep 1)
      (do-test))))


(exception-test)


Test case output:

[23:06] ~ $ guile exception-test.scm 
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/taw/exception-test.scm
;;; compiled /home/taw/.cache/guile/ccache/3.0-LE-8-4.5/home/taw/exception-test.scm.go
Error occurred

Backtrace:
Backtrace:
In ice-9/boot-9.scm:
  1752:10  7 (with-exception-handler _ _ #:unwind? _ # _)
  1685:16  6 (raise-exception _ #:continuable? _)
In /home/taw/exception-test.scm:
    18:27  5 (_ _)
In unknown file:
           4 (backtrace #<undefined>)
In system/repl/debug.scm:
   148:36  3 (print-frames #(#<frame 7f0623f102d0 backtrace> #<f…> …) …)
    72:20  2 (_)
In ice-9/boot-9.scm:
  1747:15  1 (with-exception-handler #<procedure 7f0623e1a630 at ic…> …)
In system/repl/debug.scm:
    72:40  0 (_)

system/repl/debug.scm:72:40: In procedure string->number: Wrong type argument in position 1 (expecting string): #f
[23:07] ~ $





             reply	other threads:[~2022-05-21 23:04 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-21 23:04 Thomas White [this message]
2022-09-22 18:42 ` bug#55568: (no subject) Thomas White

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220522010444.6bea02a1@dorian \
    --to=taw-gl@bitwiz.me.uk \
    --cc=55568@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).