Skip to content

TaskRunner run 메소드 #2

@SVP-PB

Description

@SVP-PB

문제

TaskRunner.run().then() 콜백에서 fulfilled 케이스만 _isDone = true를 처리하고 있어, reject 시 _isDone이 영원히 false로 남음

return this._promise = this.f().then(res => {
  this._isDone = true;
  return res;
});

영향 범위

code_6_27_28의 TaskPool클래스

  • runAll(): errorHandle이 Promise.reject(err)를 반환하므로 await에서 즉시 throw → 루프 탈출. 문제 없음.
  • runAllSettled(): errorHandle이 () => undefined로 에러를 흡수하므로 루프가 계속 진행. 아래 문제 발생.

발생 메커니즘 (runAllSettled)

  1. Promise.race()가 rejected promise로 settle → .catch()가 에러 흡수
  2. pool.findIndex(task => task.isDone) → 에러난 task는 isDone === false이므로 매칭 안 됨
  3. findIndex-1 반환 → splice(-1, 1)이 마지막 원소를 제거 (엉뚱한 정상 task 제거)
  4. 에러난 task는 pool에 잔류
  5. 다음 루프에서 task.run() 호출 → this._promise가 이미 rejected 상태로 캐싱돼있으므로 즉시 reject
  6. 1번으로 복귀

Iterator 종류에 따른 결과

무한 iterator인 경우: rejected task가 pool에 영구 잔류하면서 매 iteration마다 즉시 reject → 6번에서 1번 복귀가 무한 반복. 무한루프.

유한 iterator인 경우: splice(-1, 1)이 매번 잘못된 task를 하나씩 제거하므로 iterator 소진 후 결국 루프를 탈출하긴 하지만, 다음 문제가 발생

  • 정상 task가 pool에서 조기 제거되어 실행됨
    따라서, rejected task가 즉시 settle하면서 iterator를 의도보다 훨씬 빠르게 소진 → poolSize 기반 동시성 제어가 깨짐

수정 제안

TaskRunner.run()에서 reject 케이스도 _isDone = true 처리:

return this._promise = this.f().then(
  res => { this._isDone = true; return res; },
  err => { this._isDone = true; throw err; }
);

좋은 컨텐츠 공유해주셔서 감사합니다. 많이 배우고 있습니다. 감사합니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions