openlang

await for over ReceivePort가 isolate가 다 끝나도 끝나지 않아요

안녕하세요, 온도 CSV를 요약해 주는 작은 dart 툴을 만들고 있어요. 큰 파일들이 서로 기다리지 않도록 파일마다 isolate를 하나씩 띄워요. WSL에서 이렇게 실행해요:

dart run bin/summarize.dart data/north.csv data/south.csv -v

-v를 주면 "spawned worker" 줄이 두 번 나오고 그다음에 "got ... rows" 줄이 두 번 나와요. 행 수도 맞고요. 그러니까 worker들은 분명히 일을 하고 있어요. 그런데 그다음엔 아무것도 없어요. 표도 안 나오고, 프롬프트도 안 돌아와서 Ctrl+C를 눌러야 해요.

처음엔 worker 안의 readAsLinesSync가 뭔가를 막고 있나 했고, 그다음엔 worker 본문을 try/catch로 감싸 봤는데, 던져지는 것도 없고 달라지는 것도 없어요.

헷갈리는 건, 띄운 isolate가 전부 끝나면 main의 루프도 알아서 끝났던 걸로 기억한다는 거예요. 그래서 결과 개수를 세지 않고 await for를 쓰고 있어요. 주요 부분은 이래요:

final port = ReceivePort();

for (final p in paths) {
  await Isolate.spawn(summarizeFile, WorkOrder(p, port.sendPort));
  log.debug('spawned worker for $p');
}

final results = <FileSummary>[];
await for (final msg in port) {
  final s = msg as FileSummary;
  results.add(s);
  log.info('got ${s.path}: ${s.count} rows');
}

results.sort((a, b) => a.path.compareTo(b.path));
printTable(results);

worker는 마지막에 order.replyTo.send(FileSummary(...))만 하고 끝나요. 최근 Dart 3.x예요. 그 루프가 끝나는 시점에 뭔가 바뀐 게 있나요? 이게 왜 이런지 이해하기 전에는 결과를 모으는 부분을 다시 짜고 싶지 않아요.

영어에서 번역원문 보기

이어지는 대화 2

서로의 근거를 따라
  1. 고유 링크

    바뀐 건 없어요. ReceivePort는 저절로 닫히지 않아요. await for는 포트가 닫혀야 끝나는데, 아무도 포트를 안 닫고 있어요. isolate가 끝나는 건 해당이 안 돼요. 기억하시는 건 아마 Isolate.run이나 exit-port 트릭을 쓰던 구성일 거예요.

    가장 쉬운 해결은 결과를 세다가 paths.length개가 모이면 port.close()를 호출하는 거예요. 아니면 파일마다 Isolate.run을 쓰고 Future.wait를 쓰면 돼요.

    문서: https://api.dart.dev/stable/dart-isolate/ReceivePort-class.html

    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. context를 취소했는데도 첫 에러 이후 worker goroutine이 계속 살아 있어요 (항상 workers + 2)

    안녕하세요, 작은 Go CLI인 shotcheck를 만들고 있어요. 폴더 안의 모든 PNG가 App Store 슬롯에서 요구하는 정확한 크기인지 확인하는 도구예요. worker 풀(기본 8개)이 jobs에서 이름을 읽어서 검…

    답글 4최근 활동 go
  2. filter를 async로 바꿔도 멈춤 현상은 그대로예요

    ledgerscan으로 400k개 항목을 검색해요. run을 async로 바꾸고 main에서 await했어요. 100 ms 하트비트 Timer가 계속 돌 줄 알았거든요. 그런데 실제로는 틱이 찍히고, searching "re…

    답글 2최근 활동 dart
  3. outliers.log의 줄 수가 :outliers 카운터보다 많아요, future 8개

    8개의 future에서 시뮬레이션된 조수 측정값 20000개를 하나의 atom에 fold해요. 임계값을 넘는 측정값은 모두 outliers.log에도 append하고요. 요약은 문제없어요. :n은 항상 20000이고, :ou…

    답글 1최근 활동 clojure