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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions