Memory leaks in loops with Promise #6673

Closed
julien-f opened this Issue May 10, 2016 · 47 comments

Comments

Projects
None yet
@julien-f
Contributor

julien-f commented May 10, 2016

  • Version: Node v4.4.4 / Node v6.1.0
  • Platform: Linux 4.2.0-1-amd64 #1 SMP Debian 4.2.6-3 (2015-12-06) x86_64 GNU/Linux
;(function loop () {
  return Promise.resolve().then(loop)
})()

The code above increasingly consumes memory until it crashes with:

<--- Last few GCs --->

   16059 ms: Scavenge 1406.1 (1457.9) -> 1406.1 (1457.9) MB, 19.4 / 0 ms (+ 2.6 ms in 1 steps since last GC) [allocation failure] [incremental marking delaying mark-sweep].
   18001 ms: Mark-sweep 1406.1 (1457.9) -> 1406.1 (1457.9) MB, 1941.5 / 0 ms (+ 3.7 ms in 2 steps since start of marking, biggest step 2.6 ms) [last resort gc].
   19928 ms: Mark-sweep 1406.1 (1457.9) -> 1406.1 (1457.9) MB, 1927.5 / 0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x30f9e32b4629 <JS Object>
    1: PromiseSet(aka PromiseSet) [native promise.js:~38] [pc=0x21bc625235b] (this=0x30f9e32041b9 <undefined>,n=0x23be73509901 <a Promise with map 0x2d3fc3316dc9>,q=0,r=0x30f9e32041b9 <undefined>,t=0x23be73509961 <JS Array[0]>,u=0x23be73509941 <JS Array[0]>)
    2: PromiseInit(aka PromiseInit) [native promise.js:~53] [pc=0x21bc624d6e9] (this=0x30f9e32041b9 <undefined>,n=0x23be73509901 <a Promis...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

With Bluebird, the used memory never goes above 30MB and the program does not crash:

global.Promise = require('bluebird')

;(function loop () {
  return Promise.resolve().then(loop)
})()

@addaleax addaleax added the V8 Engine label May 10, 2016

@mscdex mscdex added the memory label May 10, 2016

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex May 10, 2016

Contributor
Contributor

mscdex commented May 10, 2016

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 May 10, 2016

Member

Is this because each promise keeps a reference to the next?

Member

Fishrock123 commented May 10, 2016

Is this because each promise keeps a reference to the next?

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

@Fishrock123 Doesn't look like that, looks like mark-sweep isn't called for whatever reason.

Could be a duplicate of #6180.
Perhaps it's even fixed by #6398 in the current master, but I can't check atm. Update: it's not, #6180 isn't fixed yet.

Member

ChALkeR commented May 10, 2016

@Fishrock123 Doesn't look like that, looks like mark-sweep isn't called for whatever reason.

Could be a duplicate of #6180.
Perhaps it's even fixed by #6398 in the current master, but I can't check atm. Update: it's not, #6180 isn't fixed yet.

@jeisinger

This comment has been minimized.

Show comment
Hide comment
@jeisinger

jeisinger May 10, 2016

Contributor

filed https://bugs.chromium.org/p/v8/issues/detail?id=5002

Firefox also runs out of memory, so maybe it's a spec thing

according to the crash, MS is executed.

Contributor

jeisinger commented May 10, 2016

filed https://bugs.chromium.org/p/v8/issues/detail?id=5002

Firefox also runs out of memory, so maybe it's a spec thing

according to the crash, MS is executed.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

@jeisinger It's not a spec thing, adding a manual gc every e.g. 1e7 iterations fixes it.
Looks very similar to #6180 — scavege is triggered instead of mark-sweep, but the memory is reclaimed only by mark-sweep, not by scavenge.

Update: I made a mistake in the test, shame on me =).

Member

ChALkeR commented May 10, 2016

@jeisinger It's not a spec thing, adding a manual gc every e.g. 1e7 iterations fixes it.
Looks very similar to #6180 — scavege is triggered instead of mark-sweep, but the memory is reclaimed only by mark-sweep, not by scavenge.

Update: I made a mistake in the test, shame on me =).

@julien-f

This comment has been minimized.

Show comment
Hide comment
@julien-f

julien-f May 10, 2016

Contributor

@jeisinger If it's a spec thing it's an issue because I don't know a better way to do a loop with promises :/

@petkaantonov What's your opinion on this?

Contributor

julien-f commented May 10, 2016

@jeisinger If it's a spec thing it's an issue because I don't know a better way to do a loop with promises :/

@petkaantonov What's your opinion on this?

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

@jeisinger No idea why the mark-sweep at the end doesn't reclaim most of that, though.

Member

ChALkeR commented May 10, 2016

@jeisinger No idea why the mark-sweep at the end doesn't reclaim most of that, though.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

@Fishrock123 @jeisinger I made a mistake in the test, ignore my previous comments. Sorry for the inconvenience.

Member

ChALkeR commented May 10, 2016

@Fishrock123 @jeisinger I made a mistake in the test, ignore my previous comments. Sorry for the inconvenience.

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 May 10, 2016

Member

If it's a spec thing it's an issue because I don't know a better way to do a loop with promises :/

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

Member

Fishrock123 commented May 10, 2016

If it's a spec thing it's an issue because I don't know a better way to do a loop with promises :/

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

Yes, it looks like all Promise objects are retained in the heap. There are twice more of them than the number of iterations, btw.

Member

ChALkeR commented May 10, 2016

Yes, it looks like all Promise objects are retained in the heap. There are twice more of them than the number of iterations, btw.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin May 10, 2016

Member

twice more of them than the number of iterations, btw.

makes sense, 2 new promises are created on each iteration

Member

vkurchatkin commented May 10, 2016

twice more of them than the number of iterations, btw.

makes sense, 2 new promises are created on each iteration

@julien-f

This comment has been minimized.

Show comment
Hide comment
@julien-f

julien-f May 10, 2016

Contributor

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

Yes but there are no other way to do async loops than using recursion (without tricks likes setImmediate() to break the stack).

Contributor

julien-f commented May 10, 2016

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

Yes but there are no other way to do async loops than using recursion (without tricks likes setImmediate() to break the stack).

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 10, 2016

Member

makes sense, 2 new promises are created on each iteration

Ah, yes, that is correct.

Member

ChALkeR commented May 10, 2016

makes sense, 2 new promises are created on each iteration

Ah, yes, that is correct.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin May 10, 2016

Member

@julien-f simple nextTick is enough in this case:

var i = 0;
;(function loop () {
  if (++i % 100000 === 0) {
    return Promise.resolve().then(() => process.nextTick(loop))
  }
  return Promise.resolve().then(loop);
})()
Member

vkurchatkin commented May 10, 2016

@julien-f simple nextTick is enough in this case:

var i = 0;
;(function loop () {
  if (++i % 100000 === 0) {
    return Promise.resolve().then(() => process.nextTick(loop))
  }
  return Promise.resolve().then(loop);
})()
@julien-f

This comment has been minimized.

Show comment
Hide comment
@julien-f

julien-f May 10, 2016

Contributor

@vkurchatkin Sure, but with real-world (spaghetti) code it's far less easy to do 😉

Contributor

julien-f commented May 10, 2016

@vkurchatkin Sure, but with real-world (spaghetti) code it's far less easy to do 😉

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin May 10, 2016

Member

To be honest, I think it works as expected. You are basically trying to build an infinite linked list

Member

vkurchatkin commented May 10, 2016

To be honest, I think it works as expected. You are basically trying to build an infinite linked list

@petkaantonov

This comment has been minimized.

Show comment
Hide comment
@petkaantonov

petkaantonov May 10, 2016

Contributor

this is a spec thing, bluebird sligthly deviates from the spec. The differences are subtle differences in callback call order in certain constructed scenarios. Theres a couple open issues in promises spec gh repo about this.

Contributor

petkaantonov commented May 10, 2016

this is a spec thing, bluebird sligthly deviates from the spec. The differences are subtle differences in callback call order in certain constructed scenarios. Theres a couple open issues in promises spec gh repo about this.

@julien-f

This comment has been minimized.

Show comment
Hide comment
@julien-f

julien-f May 11, 2016

Contributor

@petkaantonov I see :/ According to the standard, what is the best way to do a (long) loop? Do I have to do a trampoline myself using nextTick() or similar?

Contributor

julien-f commented May 11, 2016

@petkaantonov I see :/ According to the standard, what is the best way to do a (long) loop? Do I have to do a trampoline myself using nextTick() or similar?

@petkaantonov

This comment has been minimized.

Show comment
Hide comment
@petkaantonov

petkaantonov May 11, 2016

Contributor

Leave out the return statement

Contributor

petkaantonov commented May 11, 2016

Leave out the return statement

@trevnorris

This comment has been minimized.

Show comment
Hide comment
@trevnorris

trevnorris May 11, 2016

Contributor

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

While recurseive nextTick() isn't the smartest idea, it's also not unsafe.

@julien-f What @petkaantonov said. With the return you are telling the Promise to chain, which doesn't allow the promises to be GC'd until the chain is resolved. So these two are almost functionally the same:

(function foo() {
  process.nextTick(foo);
}());

(function bar() {
  Promise.resolve().then(bar);
}());

Though remember that this won't allow the event loop to continue, and will starve your application of I/O.

Contributor

trevnorris commented May 11, 2016

Unbounded recursive loops are typically not safe in JavaScript at the current time, promise or not apparently.

While recurseive nextTick() isn't the smartest idea, it's also not unsafe.

@julien-f What @petkaantonov said. With the return you are telling the Promise to chain, which doesn't allow the promises to be GC'd until the chain is resolved. So these two are almost functionally the same:

(function foo() {
  process.nextTick(foo);
}());

(function bar() {
  Promise.resolve().then(bar);
}());

Though remember that this won't allow the event loop to continue, and will starve your application of I/O.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 11, 2016

Member

Related links to what @petkaantonov said:

The differences are subtle differences in callback call order in certain constructed scenarios. Theres a couple open issues in promises spec gh repo about this.

Direct links:

Member

ChALkeR commented May 11, 2016

Related links to what @petkaantonov said:

The differences are subtle differences in callback call order in certain constructed scenarios. Theres a couple open issues in promises spec gh repo about this.

Direct links:

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR May 11, 2016

Member

Given that this is a spec thing, there seems to be nothing actionable here.
I propose we close this and redirect further discussion to promises-aplus/promises-spec repo.

Member

ChALkeR commented May 11, 2016

Given that this is a spec thing, there seems to be nothing actionable here.
I propose we close this and redirect further discussion to promises-aplus/promises-spec repo.

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis May 12, 2016

Member

I agree, closing.

Member

bnoordhuis commented May 12, 2016

I agree, closing.

@bnoordhuis bnoordhuis closed this May 12, 2016

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Jun 22, 2016

Member

/cc @littledan just in case.

Member

ChALkeR commented Jun 22, 2016

/cc @littledan just in case.

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Jun 22, 2016

We looked into fixing this once again (or rather @gsathya did) and found that it seemed like it would be impossible to fix due to this same spec reason.

We looked into fixing this once again (or rather @gsathya did) and found that it seemed like it would be impossible to fix due to this same spec reason.

@andrewstoker andrewstoker referenced this issue in elastic/elasticsearch-js Jul 14, 2016

Open

Memory usage #310

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Jul 25, 2016

Member

@littledan Btw, any chances that the spec could be fixed to allow these optimizations? There was a significant amount of discussion in promises-aplus/promises-spec.

Member

ChALkeR commented Jul 25, 2016

@littledan Btw, any chances that the spec could be fixed to allow these optimizations? There was a significant amount of discussion in promises-aplus/promises-spec.

@littledan

This comment has been minimized.

Show comment
Hide comment
@littledan

littledan Jul 25, 2016

@ChALkeR That discussion resulted in the spec we have today. Do you have any significant points that weren't mentioned there? For example, a concrete use case which is negatively impacted by the leak? I imagine most real applications will involve some real event loop behavior and not loop infinitely in microtasks. Otherwise, why not just use synchronous code?

@ChALkeR That discussion resulted in the spec we have today. Do you have any significant points that weren't mentioned there? For example, a concrete use case which is negatively impacted by the leak? I imagine most real applications will involve some real event loop behavior and not loop infinitely in microtasks. Otherwise, why not just use synchronous code?

@petkaantonov

This comment has been minimized.

Show comment
Hide comment
@petkaantonov

petkaantonov Sep 2, 2016

Contributor

@littledan The leak isn't caused by infinitely looping in microtasks, it is caused by how promise reference chain is formed when there is a resolution chain. Afaik, the reason it was not discussed or fixed in the spec is because it simply hadn't occurred to anyone at that point.

Any asynchronous loop with promises is negatively impacted by the leak. For example the natural promise equivalent of:

while (true) {
    sleep(1);
    print("slept 1 second");
}

is

(function loop() {
    return delay(1000).then(function() {
        console.log("slept 1 second");
    }).then(loop);
})()

And will leak memory unless the return statement is removed.

Contributor

petkaantonov commented Sep 2, 2016

@littledan The leak isn't caused by infinitely looping in microtasks, it is caused by how promise reference chain is formed when there is a resolution chain. Afaik, the reason it was not discussed or fixed in the spec is because it simply hadn't occurred to anyone at that point.

Any asynchronous loop with promises is negatively impacted by the leak. For example the natural promise equivalent of:

while (true) {
    sleep(1);
    print("slept 1 second");
}

is

(function loop() {
    return delay(1000).then(function() {
        console.log("slept 1 second");
    }).then(loop);
})()

And will leak memory unless the return statement is removed.

@julien-f

This comment has been minimized.

Show comment
Hide comment
@julien-f

julien-f Sep 2, 2016

Contributor

I'm wondering if it also the case with ES2016's async functions, it's probably the case with transpiling which usually implement them using promises (sometimes with generators) but I don't know about the spec.

(async () => {
  while (true) {
    await delay(1000)
    print('slept 1 second')
  }
})()
Contributor

julien-f commented Sep 2, 2016

I'm wondering if it also the case with ES2016's async functions, it's probably the case with transpiling which usually implement them using promises (sometimes with generators) but I don't know about the spec.

(async () => {
  while (true) {
    await delay(1000)
    print('slept 1 second')
  }
})()
@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Sep 2, 2016

Member

It shouldn't leak if you do anything async, like setTimeout or nextTick

Member

vkurchatkin commented Sep 2, 2016

It shouldn't leak if you do anything async, like setTimeout or nextTick

@petkaantonov

This comment has been minimized.

Show comment
Hide comment
@petkaantonov

petkaantonov Sep 2, 2016

Contributor

delay uses setTimeout

function delay(ms) {
    return new Promise(function(resolve) {
        setTimeout(resolve, ms);
    });
}
Contributor

petkaantonov commented Sep 2, 2016

delay uses setTimeout

function delay(ms) {
    return new Promise(function(resolve) {
        setTimeout(resolve, ms);
    });
}
@rjmunro

This comment has been minimized.

Show comment
Hide comment
@rjmunro

rjmunro Mar 20, 2017

If you miss out the return, you can't .catch() in one place at the end of the loop.

rjmunro commented Mar 20, 2017

If you miss out the return, you can't .catch() in one place at the end of the loop.

@craigspaeth craigspaeth referenced this issue in artsy/force Apr 5, 2017

Closed

[WIP] Use AOT compiled builds. #1177

5 of 9 tasks complete

@yshahin yshahin referenced this issue in mozilla/pdf.js May 31, 2017

Closed

Update pdf2svg.js #8461

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 26, 2017

I can't understand why this issue has left closed and unresolved.

I expected this to happen on infinite synchronous recursive loops because the stack, that makes sense. But asynchronous code does not retain the stack (it is lost, reset or whatever it happens) so I never expected a leak like this happening.
I understand that every promise keeps a reference to the next promise, it makes sense to keep the chain, but it is very inconvenient to reach problems like this.
I would love to hear any solution/workaround that does not require breaking the promise chain, or at least don't use ugly hacks that make me want to take out my eyeballs.

Thanks and regards

I can't understand why this issue has left closed and unresolved.

I expected this to happen on infinite synchronous recursive loops because the stack, that makes sense. But asynchronous code does not retain the stack (it is lost, reset or whatever it happens) so I never expected a leak like this happening.
I understand that every promise keeps a reference to the next promise, it makes sense to keep the chain, but it is very inconvenient to reach problems like this.
I would love to hear any solution/workaround that does not require breaking the promise chain, or at least don't use ugly hacks that make me want to take out my eyeballs.

Thanks and regards

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Jul 26, 2017

Member

@danielo515 this issue has been closed, because it is a problem with the spec and is not actionable. One workaround is to use async functions and while loop.

Member

vkurchatkin commented Jul 26, 2017

@danielo515 this issue has been closed, because it is a problem with the spec and is not actionable. One workaround is to use async functions and while loop.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 26, 2017

Hello @vkurchatkin thanks for your prompt response. I'm a bit worried about async functions having the same problem (according to #9339). Because node 8 has some problems with some of our tools, do you know if I can use async await in node 7 ? Maybe with an harmony flag?

I'm a bit disappointed about promises 😢

thanks again

Hello @vkurchatkin thanks for your prompt response. I'm a bit worried about async functions having the same problem (according to #9339). Because node 8 has some problems with some of our tools, do you know if I can use async await in node 7 ? Maybe with an harmony flag?

I'm a bit disappointed about promises 😢

thanks again

@TimothyGu

This comment has been minimized.

Show comment
Hide comment
@TimothyGu

TimothyGu Jul 26, 2017

Member

@danielo515 You can use the harmony flag, just not for production. #9339 was fixed in V8 5.5 which is in v7.6.0+.

EDIT: deleted unnecessarily cranky response.

Member

TimothyGu commented Jul 26, 2017

@danielo515 You can use the harmony flag, just not for production. #9339 was fixed in V8 5.5 which is in v7.6.0+.

EDIT: deleted unnecessarily cranky response.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 27, 2017

@TimothyGu , the problem is that I need it for production. According to the spec, async functions are available on node 7.10 without harmony flag, and it is the current LTS version. I'll give it a try.

Regards

@TimothyGu , the problem is that I need it for production. According to the spec, async functions are available on node 7.10 without harmony flag, and it is the current LTS version. I'll give it a try.

Regards

@TimothyGu

This comment has been minimized.

Show comment
Hide comment
@TimothyGu

TimothyGu Jul 27, 2017

Member

@danielo515 The latest LTS is v6.x. v7.x is not supported by the project at all. Why don't you just use setImmediate as a workaround until you can use v8.x? Again, if you use 7.x, or if you use any V8 experimental harmony flags, you are on your own, which is… not ideal for production.

Member

TimothyGu commented Jul 27, 2017

@danielo515 The latest LTS is v6.x. v7.x is not supported by the project at all. Why don't you just use setImmediate as a workaround until you can use v8.x? Again, if you use 7.x, or if you use any V8 experimental harmony flags, you are on your own, which is… not ideal for production.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 28, 2017

My mistake . However we have been using v7 for months on production without any problem, and as I said the harmony flag is not required for asynchronous functions

My mistake . However we have been using v7 for months on production without any problem, and as I said the harmony flag is not required for asynchronous functions

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Jul 28, 2017

Member

@danielo515 You should upgrade. v7 is end-of-life, it doesn't get security fixes. We put out a security release earlier this month that fixed a denial-of-service; v7 is vulnerable.

Member

bnoordhuis commented Jul 28, 2017

@danielo515 You should upgrade. v7 is end-of-life, it doesn't get security fixes. We put out a security release earlier this month that fixed a denial-of-service; v7 is vulnerable.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 28, 2017

@bnoordhuis update to which version ? With v.7 I mean 7.10. If you mean that I should update to node v.8 that may be a problem

@bnoordhuis update to which version ? With v.7 I mean 7.10. If you mean that I should update to node v.8 that may be a problem

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Jul 28, 2017

Member

@danielo515 either v6.x or v8.x, both are LTS release lines.

Member

bnoordhuis commented Jul 28, 2017

@danielo515 either v6.x or v8.x, both are LTS release lines.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jul 28, 2017

Thanks @bnoordhuis , I'll give a try to v8.x

Thanks @bnoordhuis , I'll give a try to v8.x

@fenixphp

This comment has been minimized.

Show comment
Hide comment
@fenixphp

fenixphp Jan 26, 2018

Can anyone explain the result of this conversation? I'm using "Node v8.9.2" but there is still a leak for cyclic use Promise or async / await functions.

Can anyone explain the result of this conversation? I'm using "Node v8.9.2" but there is still a leak for cyclic use Promise or async / await functions.

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jan 27, 2018

@fenixphp do you mean that you experiment the leak just with promises or that you experiment it both with promises and async functions ?
Theoretically this only happens on promises because they keep a chain that grows wild, which is not the case of async functions.

@fenixphp do you mean that you experiment the leak just with promises or that you experiment it both with promises and async functions ?
Theoretically this only happens on promises because they keep a chain that grows wild, which is not the case of async functions.

@fenixphp

This comment has been minimized.

Show comment
Hide comment
@fenixphp

fenixphp Jan 27, 2018

Thanks @danielo515, Experimentally, I came to the conclusion that promises begin to leak as the call chain looks like a tree. What can I replace the promises in a pair of async / await functions?

Thanks @danielo515, Experimentally, I came to the conclusion that promises begin to leak as the call chain looks like a tree. What can I replace the promises in a pair of async / await functions?

@danielo515

This comment has been minimized.

Show comment
Hide comment
@danielo515

danielo515 Jan 28, 2018

You can use async await function calls inside an infinite loop without any problem. But if you use recursion you will end with the same stack size problem.

You can use async await function calls inside an infinite loop without any problem. But if you use recursion you will end with the same stack size problem.

michurin added a commit to michurin/instant-bot that referenced this issue Apr 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment