[racket-dev] BUG: busy-waiting

From: Marc Burns (m4burns at happierface.convextech.ca)
Date: Thu Sep 4 01:56:07 EDT 2014

Yes. I forgot that, in the case I was debugging, `unzip` was wrapping
its input pipe with `make-limited-input-port`. The user port created by
`make-limited-input-port` is causing the loop. Here's an example:

#lang racket/base
(require racket/port)

(define-values (in out) (make-pipe))
(define p (make-limited-input-port in 10 #t))

(write-bytes #"hello" out)

(define buffer (make-bytes 1))
(peek-bytes-avail! buffer 6 #f p 0 1)

The `do-peek` function in port.rkt:1027 makes a nonblocking attempt to
peek from the wrapped port. When the peek is unsuccessful, it returns an
event that is ready when the wrapped port is ready and whose value is
zero.

Thus, when the wrapped port has greater than zero and fewer than `skip`
bytes available, `do-peek` is nonblocking.

The call to `peek-bytes-avail!` then loops calling `do-peek`.

I think that this could be resolved by returning

(choice-evt
  (wrap-evt progress-evt (lambda(x) #f))
  (wrap-evt
    (peek-bytes-evt skip 0 #f port)
    (lambda(x) 0)))

instead of the wrapped port event at port.rkt:1027

Then again, couldn't `do-peek` just return the appropriate
`peek-bytes-evt` when `count` is nonzero?

Marc

On Thu, Sep 04, 2014 at 05:49:17AM +0200, Matthew Flatt wrote:
> Can you provide an example?
> 
> Here's what I tried, but it blocks without busy-waiting:
> 
> ----------------------------------------
> #lang racket
> (require file/gunzip file/gzip)
> 
> (define dest (open-output-bytes))
> (deflate (open-input-bytes #"hello") dest)
> 
> (define bstr (get-output-bytes dest))
> 
> (define-values (i o) (make-pipe))
> 
> ;; Omit the last byte:
> (write-bytes bstr o 0 (- (bytes-length bstr) 1))
> 
> 'inflating...
> (inflate i (open-output-bytes))
> ----------------------------------------
> 
> 
> At Wed, 3 Sep 2014 21:02:06 -0400, Marc Burns wrote:
> > The offending function in my case seems to be peek-bytes-avail!
> > 
> > The busy wait is entered on line 284 of collects/file/gunzip.rkt. Here's
> > what happens when I add some tracing to gunzip.rkt and then try to
> > inflate a Racket pipe:
> > 
> > ...
> > +           (displayln "before read-bytes!")
> >             (read-bytes! buffer input-port 0 (max 0 (- buf-max MAX-LOOKAHEAD)))
> > +           (displayln "after read-bytes!")
> >             ;; Even though we won't actually use bytes that we "unwind",
> >             ;; setting `buf-pos' to the number of unwound bytes lets us
> >             ;; keep track of how much to not actually read at the end.
> >             (set! buf-pos (min MAX-LOOKAHEAD buf-max)))
> >           ;; Peek (not read) some available bytes:
> > +         (displayln "before peek-bytes-avail!")
> >           (let ([got (peek-bytes-avail! buffer buf-pos #f input-port buf-pos 
> > BUFFER-SIZE)])
> > +           (displayln "after peek-bytes-avail!")
> > ...
> > +  (trace READBITS)
> > 
> > Output:
> > 
> > ...
> > >(READBITS 9)
> > <#<void>
> > >(READBITS 9)
> > before read-bytes!
> > after read-bytes!
> > before peek-bytes-avail!
> > 
> > That's it. Racket is busy-waiting in peek-bytes-avail!
> > 
> > On Wed, Sep 03, 2014 at 10:52:18PM +0200, Jan Dvořák wrote:
> > > Hello,
> > > 
> > > I am hitting a rather uncomfortable bug that causes runtime to start
> > > internal busy-waiting at around:
> > > 
> > > #0  scheme_block_until(_f=<syncing_ready>,
> > > fdf=<scheme_syncing_needs_wakeup>)
> > >    at ../src/thread.c:5199
> > > #1  do_sync (name="sync", with_break=0, with_timeout=0)
> > >    at ../src/thread.c:7109
> > > 
> > > It goes through ../src/thread.c:5190, which Matthew mentions in one of his
> > > recent patches.
> > > 
> > > The code that manages to trigger this have been written under NDA and cannot
> > > be published. I have not yet managed to reproduce the issue separately, but
> > > it seems that this might not be the only instance:
> > > 
> > >    (09:28:36 PM) m4burns: Mordae: I'm having a similar problem somewhere in
> > >                           `inflate`. Haven't applied a debugger yet, but
> > >                           there's certainly no busy waiting in the script.
> > > 
> > > I am stuck and would like to ask for your help.
> > > 
> > > Best regards,
> > > Jan Dvorak
> > > 
> > > 
> > > 
> > > _________________________
> > >  Racket Developers list:
> > >  http://lists.racket-lang.org/dev
> > > 
> > _________________________
> >   Racket Developers list:
> >   http://lists.racket-lang.org/dev
> 

Posted on the dev mailing list.