[racket-dev] BUG: busy-waiting

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Sep 4 18:06:41 EDT 2014

Thanks! I've pushed a repair.

At Thu, 4 Sep 2014 01:56:07 -0400, Marc Burns wrote:
> 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.