ok, I got a segfault in a program and I don't quite understand the cause.
This code:
(define (string-escape string chars #!optional (escape (lambda (c) (print #\ c))) port) (let ((pred? (%string-charset->pred chars)) (output (or port (open-output-string "")))) (with-output-port output (string-for-each (lambda (c) (if (pred? c) (escape c) (print c))) ; this is where the anti-magic happens string)) (or port (get-output-string output))))
is called many times (inside a function called sql-quote-object). On line 1420 of my input file, it segfaults. I've had a hard time reproducing this in a more confined context, but I will if this doesn't turn out to be known or easily deducible.
If I change that (print c) to (display c), all is well. At first I was under the impression that the output was leaking because line 1421 turned out to contain a literal ^H. The progam exhibits the same behavior with all the lines containing control characters removed from the input. Also exhibits the same behavior in a file containing multiple copies of the first 1419 lines of the input, so I'm pretty confident it doesn't have anything to do with the input.
I'm sorry this message is so rough -- I really will create a responsible bug report if this vague one doesn't give someone with a good understanding of the internals something to go on.
Does print buffer it's output, by any chance?
Afficher les réponses par date
gaa. Forgot all the version stuff:
it segfaults in gsi on linux, version 4b22.
Lang Martin wrote:
ok, I got a segfault in a program and I don't quite understand the cause.
Your code is using %string-charset->pred which you don't specify in your mail.
You could run Gambit under gdb. This usually gives hints.
BTW are you using (declare (not safe)) ?
I think print
(define-prim (print
#!key (port (macro-absent-obj))
#!rest body)
(macro-force-vars (port)
(let ((p
(if (##eq? port (macro-absent-obj))
(macro-current-output-port)
port)))
(macro-check-output-port p 2 (print port: p . body)
(##display body p)))))
whereas
(define-prim (##display obj port #!optional (max-length ##max-fixnum))
(if (macro-character-output-port? port)
(begin
(##write-generic-to-character-port
'display
port
(macro-character-port-output-readtable port)
(macro-if-forces #t #f)
max-length
obj)
(##void))
((macro-port-write-datum port) port obj #f)))
so I don't really see why choosing one over the other should matter.
Christian.
On Apr 26, 2007, at 8:45 AM, Christian Jaeger wrote:
Your code is using %string-charset->pred which you don't specify in your mail.
I omitted it because it didn't seem to matter -- the segfault does not occur if I simply change print to display in the main loop. Well, that once in the main loop, since it's also called from the default value of escape.
However, here it is:
(define (%string-charset->pred obj) (cond ((procedure? obj) obj) ((list? obj) (lambda (c) (memq c obj))) ((string? obj) (%string-charset->pred (string->list obj))) ((char? obj) (lambda (c) (char=? c obj)))))
It simply creates a predicate from "abc" or '(#\a #\b #\c) in the same way.
BTW are you using (declare (not safe)) ?
I am not, and should have said so. The code that crashes is interpreted, not compiled, and gsi was built with just the standard options. I didn't even bother with --single-host or anything when I installed it.
I think print [...]
Ah. That's surprising. I'll go ahead and try to duplicate the fault then, and see if I can get get gdb to help me narrow in on the problem. Thanks, and other thoughts are welcome.
On my 4.0 beta 21 installation (compiled with single-host and shared), this doesn't segfault:
(define (string-escape string chars #!optional (escape (lambda (c) (print #\ c))) port) (let ((pred? (%string-charset->pred chars)) (output (or port (open-output-string "")))) (with-output-to-port output (& (string-for-each ;; <--from srfi-13 (lambda (c) (if (pred? c) (escape c) (print c))) ; this is where the anti-magic happens string))) (or port (get-output-string output))))
Note that I did change it at two locations: - with-output-port is not present in beta 21 (neither did I find it in the manual of beta 22), so I did change to with-output-to-port - with-output-to-port expect a thunk as second argument, so I did wrap it in (& ) where this is a macro defined by myself (I deserve the right to use my own code too, now :^)):
(define-macro (& first . rest) `(lambda() ,first ,@rest))
Christian.
On Apr 26, 2007, at 10:48 AM, Christian Jaeger wrote:
On my 4.0 beta 21 installation (compiled with single-host and shared), this doesn't segfault:
It doesn't segfault until it's been running for a while.
- with-output-port is not present in beta 21 (neither did I find it in
the manual of beta 22), so I did change to with-output-to-port
The file is a bit convoluted, but I have collected all the library bits that weren't showing before. It crashes on my macbook as well as on the linux box.
Program received signal SIGSEGV, Segmentation fault. 0x080c4269 in ___garbage_collect ()
says gdb. Which of course makes sense in light of it not failing for a while.
I can avoid the crash by creating less garbage (making a smaller string -- 40 works for me) or by changing print to display, as previously reported.
both of those bits are at the bottom of the file.
On my b21 installation, when loading it into gsc, it never segfaults. When running it through gsi-script, it does segfault. Albeit in another function for me (not really surprising), always in mark_continuation:
0xb7c99c10 in mark_continuation () from /usr/local/Gambit-C/current/lib/libgambc.so
but the stack seems corrupted anyway:
bt
#0 0xb7c32c10 in mark_continuation () from /usr/local/Gambit-C/current/lib/libgambc.so #1 0x00000016 in ?? () #2 0x000b7973 in ?? () #3 0x00000000 in ?? () #4 0x0000001a in ?? () #5 0x00000000 in ?? () #6 0xb7ef6680 in completed.1 () from /usr/local/Gambit-C/current/lib/libgambc.so #7 0xb7ef2020 in __JCR_LIST__ () from /usr/local/Gambit-C/current/lib/libgambc.so #8 0x00000000 in ?? () #9 0x00000000 in ?? () #10 0x00000002 in ?? () #11 0xb7c319c3 in ___garbage_collect () from /usr/local/Gambit-C/current/lib/libgambc.so #12 0x00000000 in ?? () .... #697 0x00000000 in ?? () #698 0x00000000 in ?? () #699 0xb7b529f8 in ?? () #700 0xbfc1a3a4 in ?? () #701 0xb7f153b4 in _dl_map_object () from /lib/ld-linux.so.2
gdb /usr/local/Gambit-C/current/bin/gsi .. run ..
(load "printsegvbug2script.scm")
"/home/chris/schemedevelopment/gambit/work/printsegvbug2script.scm"
(main)
Program received signal SIGSEGV, Segmentation fault. 0xb7c59c10 in mark_continuation () from /usr/local/Gambit-C/current/lib/libgambc.so (gdb)
but :
chris@elvis-5 work > gdb /usr/local/Gambit-C/current/bin/gsc GNU gdb 6.3-debian Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) run Starting program: /usr/local/Gambit-C/4.0b21/bin/gsc Failed to read a valid object file image from memory. Gambit Version 4.0 beta 21
(load "printsegvbug2script.scm")
"/home/chris/schemedevelopment/gambit/work/printsegvbug2script.scm"
(main)
(time (let lp ((count 20000)) (or (= 0 count) (begin (sql-parse-object (make-string 50 #\a)) (lp (- count 1)))))) 7667 ms real time 7668 ms cpu time (7628 user, 40 system) 662 collections accounting for 2259 ms real time (2280 user, 4 system) 452458088 bytes allocated 119 minor faults no major faults #t
(main)
..
(main)
..
never segfaults
Seems keyword handling somehow interrelates (actually I was suspecting that consing in the print parameters may be the reason, but these example show that it's not consing per se):
(print c (list c 1 3)) does not segfault (print (list c 1 3)) segfaults
Could just be by coincidence, of course. (I would guess the problem is somewhere in memory handling in the buffer writing/copying code in string port operations?)
Christian.
On Apr 26, 2007, at 12:31 PM, Christian Jaeger wrote:
Seems keyword handling somehow interrelates (actually I was suspecting that consing in the print parameters may be the reason, but these example show that it's not consing per se):
(print c (list c 1 3)) does not segfault (print (list c 1 3)) segfaults
Could just be by coincidence, of course.
There is (was?) a garbage-collection bug related to processing of keyword arguments.
Brad
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 26-Apr-07, at 12:03 PM, Lang Martin wrote:
Program received signal SIGSEGV, Segmentation fault. 0x080c4269 in ___garbage_collect ()
says gdb. Which of course makes sense in light of it not failing for a while.
I can avoid the crash by creating less garbage (making a smaller string -- 40 works for me) or by changing print to display, as previously reported.
both of those bits are at the bottom of the file.
The handling of #!key parameters when combined with a #!rest parameter has a nasty bug. When there is not enough space on the heap to handle the parameters, the runtime system saves the parameters in a vector (which takes less space than a list), then calls the GC and then retries the procedure call (by copying the parameters back to the stack and registers). I'll investigate further what's going wrong.
For now stay away from "print" (which uses #!key and #!rest) and use "display".
Marc