life is egg

[PINTOS] syn_read 와... 인터럽트 검증 관련 오류 본문

sw정글/C

[PINTOS] syn_read 와... 인터럽트 검증 관련 오류

삶은계란진재혁 2024. 5. 14. 01:28

 

뜬다... 오류..! 

 

해당 문제는 Deny Write on Executables 를  구현하고 동기화 관련된 테스트 중 발생한 오류이다 .

 

 

백트레이스 해서  call stack을 분석해보면 exec 시스템콜에서 내부 함수들을 호출하다가 최종적으로 real_time_sleep 에서 

해당 부분의 검증에서 검증에 실패해서 발생한 오류이다 ... 즉 인터럽트를 받을 수 있는 상태여야하는데 인터럽트를 막아논 상태

	ASSERT(intr_get_level() == INTR_ON);

 

호출 스택을 살펴보면 우리가 수정한 함수는 process_exec 부터 load까지 극히 일부분이고 심지어 이 함수에서 인터럽트를 변경하는 부분이 없어서  어디가 잘못된 것인지 의문이였다

 

 

따라서 exec 시스템콜 호출뿐만아니라 해당 함수에서 사용하는 fork 와 wait 시스템 콜도 살펴보았다.

 

동기화 테스트중 sys-read 코드이다

/* Spawns 10 child processes, all of which read from the same
   file and make sure that the contents are what they should
   be. */

#include <random.h>
#include <stdio.h>
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
#include "tests/filesys/base/syn-read.h"

static char buf[BUF_SIZE];

#define CHILD_CNT 10

void
test_main (void) 
{
  pid_t children[CHILD_CNT];
  int fd;

  CHECK (create (file_name, sizeof buf), "create \"%s\"", file_name);
  CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
  random_bytes (buf, sizeof buf);
  CHECK (write (fd, buf, sizeof buf) > 0, "write \"%s\"", file_name);
  msg ("close \"%s\"", file_name);
  close (fd);

  exec_children ("child-syn-read", children, CHILD_CNT);
  wait_children (children, CHILD_CNT);
}

 

 

fork와 wait 시스템 콜도 수정하면서 검증해봐도 문제가 없어보이고.. 또 다른 테스트들은 통과하는데 동기화 부분에서만 터져나가니

 

내 맨탈도 같이 터져나갔다.

 

결국 최후의 방법으로 테스트를 통과하기 위해 우리가 수정한 함수에서 들어가는 쪽에서 인터럽트 레벨을 강제로 조정해서 해당 오류를 해결해보자고 했고..

 

인터럽트 레벨을 ... 강제적으로 조정을해서... 그래... 이제는 통과할 수밖에 없다... 라는 생각을 가지고 테스트를 돌렸다..

 

..!! 하지만 테스트 결과는 여전히 실패였다 ... 왜..?!

 

이때 우리팀은 인터럽트 레벨을 조정해 주었는데도  같은 오류가 발생하는지 이해 할수 없었다.

 

..!!

 

 

 

그래서 우리팀은 ... 프로젝트 진행도중 작성한 모든 코드들이 의심되기 시작했고,, 일단 우리팀이 인터럽트 레벨을 직접적으로 조정한 부분이 있는지 확인해보기로 했다 ..

 

 

 

 

앗차차차.... 찾아버렸다 ...

 

1주차때.. 원자성에 대한 발표를 준비하면서 인터럽트 레벨을 조정해보면서 실험을 하다가 미처 주석을 해제 하지 못한 부분이 있다는 것을 .... 너무나도 늦게 깨달아버렸다 ..

 

 

문제의 주석을 해제하고 난 뒤에 동기화와 관련된 테스트를 통과할 수있었다

 

 

무튼 이제 왜 오류가 나왔는지 알아봐야한다

 

해당 문제의 함수는 우선순위 스케쥴링에서 우선순위를 비교후 기부를 하는 함수인데 .. 이 함수에서는 원자성을 보장하기위해 함수의 내부의 코드를 실행할때는 인터럽트를 끄고 실행해야한다 .

 

donate_priority를   호출하는 함수는   원자성을 보장하기 위한 함수중 lock_acquire...에서만 호출 해주고있었다 ..

 

 

 

락과 관련된 함수들은 핀토스 프로젝트 1부터 사용 하고 있었는데 ... 왜 오류가 지금까지 나타나지 않고... 지금에서야 문제가 터지는지 찾아보았는데...

 

락을 획득하는 lock_acquire 함수는 다양한 곳에서 호출하면서 사용 하고 있었는데 ... syn_read와 syn_write 이외의 테스트에서는 락 획득 이후 호출해주는 함수들이 인터럽트 레벨을 검증하주는 함수가 없어서.. 그래서 지금까지 잘못된 코드임에도 테스트를 통과 할 수 있었다.

 

추가로 왜 강제로 인터럽트 레벨을 바꿔도 해당 테스트가 실패하는 지 알 수 있었는데 ...

 

백트레이스 로그에서 찍히는 read disk 내부에서 락획득을 호출해 주고있고. 락획득 내부에서 문제의 함수인 도네이션 기부를 해주는 함수를 호출해주고 있기 때문에 우리팀이 밖에서 인터럽트 레벨을 강제로 조정해도 테스트에 실패하던것 ...

 

 

 

배운점

  • 테스트가 통과 되었다고 해서 완벽한 코드가 아니다..
  • 디버깅 메세지 위주로 디버깅하는걸 ... 잊지말자 ... 디버거는 ... 힌트를 주고있다.....

인터럽트 레벨위주로 .. 살펴봐달라는 디버거의 처절한 외침 ...

  • 추가로 테스트를 위한 코드를 수정할때는. . 테스트 브랜치를 파서 진행을 해야... 나중에 오류전파를 방지할수 있다는걸 ... 몸으로 체험하며 배웠다 ..

'sw정글 > C' 카테고리의 다른 글

[PINTOS] victim frame  (0) 2024.05.28
[PINTOS] 구조체 초기화  (0) 2024.05.21
[PINTOS] priority conditon variable test  (0) 2024.05.03
[PINTOS] 타이머 인터럽트의 주체는  (0) 2024.04.29
[Malloc] Implict  (0) 2024.04.18
Comments