openlang

정지된 셸 작업은 끝난 작업이 아니다

멈춘 프로세스를 끝난 프로세스로 취급하는 감독자 규칙에 대해 질문이 있어요.

셸 단계가 입력 파일을 쓰고, 그 뒤에 소비자가 예약돼 있어요. 그런데 쓰는 쪽이 도중에 일시 정지돼요. 감독자는 프로세스가 멈췄다는 이벤트를 받고, 제안된 규칙은 그걸 보고 소비자를 띄워요.

멈춘 건 끝난 게 아니에요. Bash에서 일시 정지된 작업은 jobs에 Stopped로 남아 있고, fg나 bg로 바로 다시 실행 상태가 돼요. 출력 검증도 아직 아무도 안 했고요.

그럼 감독자는 소비자를 시작하기 전에 무엇을 확인해야 하고, 쓰는 쪽이 일시 정지된 동안에는 그 상태를 어떻게 나타내야 할까요?

이어지는 대화 3

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

    Stopped는 기다리는 상태예요. 감독 프로세스도 그렇게 보여 줘야 해요. fg나 bg로 writer가 다시 실행 상태가 돼도 consumer는 아직 준비되지 않았어요. 준비되려면 두 단계를 거쳐야 해요. 먼저 writer가 성공적으로 끝나야 해요. 그다음 consumer가 그 파일을 실제로 쓸 수 있는지 확인해요.

    감독을 Python으로 짜도 마찬가지예요. 각 태스크는 자기 외부 단계가 실제로 끝나기를 await해야 해요. TaskGroup은 블록을 빠져나갈 때 멤버 태스크들을 기다리니까, stop 이벤트를 보자마자 반환하는 멤버는 엉뚱한 단계를 완료로 표시하는 셈이고, 그룹은 아무 불평 없이 넘어가요. 제대로 끝난 태스크라도 무언가가 그 결과에 기대기 전에 출력을 확인해야 해요. 그리고 기다리는 동안 CancelledError는 삼키지 말고 흘려보내 주세요. 그래야 감독을 취소하는 게 여전히 먹혀요.

  2. 고유 링크

    재밌는 건요, PowerShell은 같은 단어를 거의 정반대 상태에 써요. 백그라운드 작업은 Stop-Job 뒤에 Stopped가 되는데, 끝나서 다시 안 돌아온다는 뜻이에요. 멈췄다 다시 이어지는 상태는 Suspended이고 그것도 일부 작업 종류에서만 돼요. 그러니 셸을 넘나들며 상태를 이름으로 맞추는 감독기는 양쪽 방향으로 다 틀려요. 소비자 쪽은 Completed에 출력 파일 검사까지 통과해야 열고, Stopped를 포함한 나머지는 전부 준비 안 됨으로 볼 것 같아요. 여담인데요, 작업 객체는 상태를 속성으로 바로 줘요. jobs 출력을 긁을 필요가 없는데, 파이프라인에 객체가 흐르는 게 좋은 이유의 절반이 그거예요.

  3. 고유 링크

    out.tmp에 써. wait "$pid"가 0을 돌려줄 때만 mv out.tmp out 하고 소비자를 띄워. 스크립트에선 작업 제어가 꺼져 있어서 wait는 멈춘 동안에도 계속 기다려. 작업 제어가 켜져 있으면 멈춤 때문에 0이 아닌 상태로 일찍 끝날 수 있는데, 그래도 검사에서 걸러져. 반쯤 쓴 파일은 진짜 이름을 절대 못 얻어.

같은 질문의 다른 갈래

  1. module-info.java는 의존성 목록이 아니다

    모듈을 쓰는 Java 프로젝트는 의존성을 두 번 적습니다. 빌드 스크립트는 어떤 아티팩트를 받아서 어느 경로에 둘지 말하고, module-info.java는 이 모듈이 어떤 모듈을 requires 하는지 말합니다. 두 목록이…