[plt-dev] Error message from test-engine

From: Eli Barzilay (eli at barzilay.org)
Date: Mon Nov 16 20:36:41 EST 2009

On Nov 16, Carl Eastlund wrote:
> I got the following error while trying to modify the way Dracula uses
> check-expect tests:
> 
> force: reentrant promise gc-on-bitmap
> [...]
> 
> I don't think anything I did should cause this, but I'm not sure
> quite what happened so I can't say for sure.  I do know my program
> had two check-expect tests, and when this error showed up the
> check-expect output displayed three results (my first test once and
> my second test twice).
> 
> Does anyone know what might be causing this?

This error happens when a promise is forced while it is forced.  For
example:

  -> (define p (delay (force p)))
  -> (force p)
  force: reentrant promise p

This is especially tricky when multiple threads are involved:

  -> (define p (delay (sleep 5)))
  -> (thread (lambda () (force p)))
  #<thread>
  -> (force p)
  force: reentrant promise p

which could be a problem since threads are involved.

As for what Robby said -- I comitted some major extension to
`scheme/promise', but the plain `delay'/`force'/`lazy' should be doing
exactly the same thing they did before, so no *new* problems should be
introduced.

So, what I think you should do now is:

1. Try to undo my changes to `scheme/promise' and see if you get the
   same error.  You can just use the contents of the file from 4.2.2
   for this.  If it doesn't fail, then there might be a bug in the
   extension, and I'll need some minimal-ish code that reproduces it.

2. But I think that it's likely it will fail too.  In that case,
   you're probably running against the thread problem that I've
   demonstrated above.  (If you look at your stack trace, you'll see
   that there is one `force/generic', which is what you'd get from my
   thread example, but the first one will have two.)

   The good news is that one of the new extensions that I added is
   `delay/sync' -- this is a kind of a promise that can be forced from
   multiple threads, the first one will compute it and the rest will
   block until it's ready.  So, if it does fail, you should look
   around for code that uses `delay'/`force', and see if you can fix
   it by using `delay/sync'.

BTW, this restriction that makes plain promises less useful with
multiple threads is relatively new (since v4).  The older version
wouldn't throw that error -- but it would have the obvious race
conditions, which means that the promise will be forced multiple time,
and one will get to stay.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the dev mailing list.