[Haskell-cafe] Timeout exceptions sometimes don't work, even in pure (non FFI) code

Job Vranish job.vranish at gmail.com
Tue Feb 1 18:02:03 CET 2011


Hmm, that's good to know.

It looks like it also works for most data dependency cases.

works = let
  a = b
  b = a
  in a

main = timeout 1 $ evaluate $ works

This terminates even with optimizations.

So I think I'll be able to work around it.
I wish timeout worked a little more consistently. This behavior is quite
annoying.

Thanks for your help,

- Job

On Tue, Feb 1, 2011 at 11:18 AM, Daniel Fischer <
daniel.is.fischer at googlemail.com> wrote:

> On Tuesday 01 February 2011 16:40:43, Job Vranish wrote:
> > I'm trying to test some properties with quickcheck. If these tests fail,
> > they will almost certainly fail by nontermination.
> > I've been using the 'within' function to catch these nontermination
> > cases. However, I was surprised to find that this doesn't always work.
> > 'within' uses the 'timeout' function under the hood. Here is an example
> > that demonstrates the problem:
> >
> > import System.Timeout
> > import Control.Exception
> >
> > works :: Int -> Int
> > works x = sum $ cycle [x]
> >
> > doesntWork :: Int -> Int
> > doesntWork x = last $ cycle [x]
> >
> > test1 = timeout 1 $ evaluate $ works 5 == 5            -- terminates
> > test2 = timeout 1 $ evaluate $ doesntWork 5 == 5   -- never terminates
> >
> >
> > test1 returns Nothing as expected, but test2 never terminates. Why?
>
> When compiled with optimisations, works doesn't terminate either.
>
> I believe it's because works actually does some work and allocations
> (without optimisations), while doesntWork is a non-allocating loop.
> GHC only makes context switches on allocations, so with a non-allocating
> loop, the timeout thread never gets to run to see whether the time limit is
> exceeded.
> Without optimisations, sum allocates thunks, with optimisations it becomes
> a tight loop not hitting the heap. `last $ cycle [x]' becomes a tight loop
> even without optimisations.
>
> >
> > I thought timeout exceptions are supposed to always work with pure (non
> > FFI) Haskell code.
> > Is there any way I can work around this?
>
> Make sure your tests always allocate, or write them as IO stuff and call
> yield (or threadDelay) within the loops to let GHC make some context
> switches.
>
> >
> > I'm using ghc 6.12.2
> >
> > Thanks,
> >
> > - Job
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110201/602b4fd7/attachment-0001.htm>


More information about the Haskell-Cafe mailing list