[운체] 오늘의 삽질 - 0730

방법이있지·2025년 7월 30일
post-thumbnail

fork 실패 예외처리

fork가 실패하는 경우

  • process_fork 함수는 복제 과정에서 문제가 발생할 시 TID_ERROR을 반환해야 함
// [부모] process_fork 함수
tid_t result = thread_create(name, PRI_DEFAULT, __do_fork, fa);

// 자식 쓰레드 생성에 실패하면 TID_ERROR 반환
if (result == TID_ERROR){
    free(fa);
    return TID_ERROR;
}
  • (1) thread_create가 자식 쓰레드 생성에 실패한 경우

    • thread_create는 실패 시 TID_ERROR 반환, 쉽게 예외처리 가능
  • (2) 자식 프로세스의 __do_fork에서 부모의 자원을 복제하는 데 실패한 경우

    • e.g., PML4 테이블, 파일명시자 테이블...
    • 복제에 실패했음을 자식에서 부모 프로세스로 전달해야 함

구조체를 활용

struct fork_aux {
	struct thread *parent;
	struct intr_frame *parent_if;
	bool success;                       // 복제의 성공 여부 표시
};

struct thread *curr = thread_current();
	// [구현 7-2] 자식에게 부모의 인터럽트 프레임 전달하기.
	struct fork_aux *fa = malloc(sizeof(struct fork_aux));
	if (fa == NULL){
		return TID_ERROR;
	}
	fa -> parent = thread_current();
	fa -> parent_if = if_;
	fa -> success = false;          // false로 초기화

	// 자식 쓰레드 생성 및 __do_fork 호출
	tid_t result = thread_create(name, PRI_DEFAULT, __do_fork, fa);
  • 자식 프로세스의 __do_fork에 여러 인자를 넘기기기 위해, 구조체로 묶고 포인터로 전달
  • success 멤버: false로 초기화, 복제에 성공했을 때만 true로 변경
// [자식] __do_fork 함수

current->pml4 = pml4_create();
if (current->pml4 == NULL)
    goto error;

if (!pml4_for_each(parent->pml4, duplicate_pte, parent))
    goto error;

struct file *copy = file_duplicate(parent_file);
if (copy == NULL)
    goto error;

// 성공한 경우 success 멤버를 true로 변경
((struct fork_aux *)(aux)) -> success = true;
do_iret (&if_);
// 생략

error:
    // 실패한 경우, 바로 error로 이동하므로 success는 false로 유지됨
	sema_up(&(parent -> f_sema));
	thread_exit ();     // 자식 쓰레드 종료
  • 자식 프로세스에서 복제에 실패한 경우, error 레이블로 이동 -> successfalse 유지
    • 이후 복제에 실패한 자식 쓰레드를 thread_exit으로 종료시킴
  • 모든 복제에 성공한 경우만, 값을 true로 변경하고, do_iret으로 사용자모드로 복귀
// [부모] process_fork
sema_down(&(thread_current()->f_sema));

// fa는 __do_init에 전달한 구조체
if (!(fa -> success)){
    result = TID_ERROR;
}
free(fa);
return result;
  • 이후 부모 프로세스에서 자식이 success 멤버를 false로 남겨둔 경우, TID_ERROR를 반환해 복제실패 처리

회고

  • 핀토스에선 부모, 자식 프로세스 간 복잡한 상호작용이 이루어짐
  • 간단한 프로그램에선 에러가 발생할 시 즉시 종료시키면 그만이지만, 핀토스에서는 상호작용을 고려하여 예외 상황을 명확히 처리해야 함
  • 프로그램의 규모가 커질수록 예외 처리가 중요해짐을 몸소 느낌
profile
뭔가 만드는 걸 좋아하는 개발자 지망생입니다. 프로야구단 LG 트윈스를 응원하고 있습니다.

0개의 댓글