Jens Thiele | 9 Mar 19:01

segmentation fault using vport

Hi,

I get a segmentation fault if the buffer is smaller than something to
be written into the buffer.

,----[ gosh -V ]
| Gauche scheme interpreter, version 0.8.13 [utf-8,pthreads]
`----

Small test:

#!/usr/bin/env gosh
(use gauche.uvector)
(use gauche.vport)

(let1 oport (make <buffered-output-port> :buffer-size 10)
  (slot-set! oport 'flush
	     (lambda(uv fl)
	       (write-block uv)
	       (u8vector-length uv)))
  (with-output-to-port
      oport
    (lambda()
      (display "biggerthanbuffer\n"))))

,---- useless backtrace
| Program received signal SIGSEGV, Segmentation fault.
| [Switching to Thread 0xb7c056b0 (LWP 23334)]
| 0xb7d6b8c0 in pthread_getspecific () from /lib/i686/cmov/libpthread.so.0
| (gdb) i s
(Continue reading)

Shiro Kawai | 10 Mar 04:18

Re: segmentation fault using vport

Hi Jens,

The direct cause of segfault is this: Your 'flush' procedure
is invoked in the dynamic extent of with-output-port, so the
write-block procedure tries to write out the content into the
the <buffered-output-port> itself.  Which is already full,
so it invokes flush procedure again, and that caused the
infinite loop.  This loop involves C API call so SETFAULT
results when the process ran out the C stack.

Apparently there needs some safety net mechanism in Gauche
to detect this situation.   For the time being, make sure
your sink is different from the port itself, e.g.:

(let1 oport (make <buffered-output-port> :buffer-size 10)
  (let1 out (current-output-port)
    (slot-set! oport 'flush
               (lambda(uv fl)
                 (write-block uv out)
                 (u8vector-length uv))))
  (with-output-to-port
      oport
    (lambda()
      (display "biggerthanbuffer\n"))))

--shiro

From: Jens Thiele <karme <at> berlios.de>
Subject: [Gauche-devel] segmentation fault using vport
Date: Sun, 09 Mar 2008 19:04:40 +0100
(Continue reading)

Jens Thiele | 10 Mar 09:19

Re: segmentation fault using vport

Shiro Kawai <shiro <at> lava.net> writes:

> Hi Jens,
>
> The direct cause of segfault is this: Your 'flush' procedure
> is invoked in the dynamic extent of with-output-port, so the
> write-block procedure tries to write out the content into the
> the <buffered-output-port> itself.

Ah! Yes of course! I missed that one. Thanks.

> Which is already full,
> so it invokes flush procedure again, and that caused the
> infinite loop.  This loop involves C API call so SETFAULT
> results when the process ran out the C stack.

Okay.

> Apparently there needs some safety net mechanism in Gauche
> to detect this situation.   For the time being, make sure
> your sink is different from the port itself, e.g.:
>
> (let1 oport (make <buffered-output-port> :buffer-size 10)
>   (let1 out (current-output-port)
>     (slot-set! oport 'flush
>                (lambda(uv fl)
>                  (write-block uv out)
>                  (u8vector-length uv))))
>   (with-output-to-port
>       oport
(Continue reading)


Gmane