felixSchl/purescript-pipes

Very large/infinite producers cause stack overflow

Closed this issue · 2 comments

Nice to meet you!

Producers seem to cause stack overflow if they emit too many elements.

Here is a minimal example:

module Main where

import Prelude

import Effect (Effect)
import Pipes (for)
import Pipes.Core (runEffect)
import Pipes.Prelude (repeatM)

main :: Effect Unit
main = runEffect $ for (repeatM (pure 0)) (\_ -> pure unit)

Expected result: run forever without crash

Actual result:

$ spago run
[info] Installation complete.
[info] Build succeeded.
/tmp/foo/output/Pipes.Core/index.js:144
            var go = function (p) {
                              ^

RangeError: Maximum call stack size exceeded
    at go (/tmp/foo/output/Pipes.Core/index.js:144:31)
    at Respond.value1 (/tmp/foo/output/Pipes.Core/index.js:152:32)
    at /tmp/foo/output/Pipes.Core/index.js:103:37
    at go (/tmp/foo/output/Pipes.Internal/index.js:294:28)
    at /tmp/foo/output/Pipes.Internal/index.js:298:20
    at go (/tmp/foo/output/Pipes.Core/index.js:102:96)
    at /tmp/foo/output/Control.Monad/index.js:51:79
    at /tmp/foo/output/Effect/foreign.js:12:14
    at /tmp/foo/output/Effect/foreign.js:12:20
    at /tmp/foo/output/Effect/foreign.js:12:16
[error] Running failed; exit code: 1

or alternatively:

$ spago run
[info] Installation complete.
[info] Build succeeded.
/tmp/foo/output/Pipes.Core/index.js:146
                    return Control_Bind.bind(Pipes_Internal.bindProxy(dictMonad))(fb$prime(p.value0))(function ($79) {
                                                                                                               ^

RangeError: Maximum call stack size exceeded
    at /tmp/foo/output/Pipes.Core/index.js:146:112
    at go (/tmp/foo/output/Pipes.Internal/index.js:294:28)
    at /tmp/foo/output/Pipes.Internal/index.js:290:83
    at /tmp/foo/output/Effect/foreign.js:12:14
    at /tmp/foo/output/Effect/foreign.js:12:16
    at /tmp/foo/output/Effect/foreign.js:12:20
    at /tmp/foo/output/Effect/foreign.js:12:16
    at /tmp/foo/output/Effect/foreign.js:12:20
    at /tmp/foo/output/Effect/foreign.js:12:20
    at /tmp/foo/output/Effect/foreign.js:12:20
[error] Running failed; exit code: 1

Since I'm new to pipes (I mainly use conduit in Haskell), perhaps I'm misusing something?

Also tried replicateM 1000000 (pure 0) and repeatM (pure 0) >-> take 1000000 but got the same result (crash).

Effect is not a stack-safe monad. You might want to try using Aff, which is stack-safe.

Thank you for the input! I was able to avoid stack overflow with Aff. (Added launchAff_ $ just before runEffect)