AI Briefing

strace로 찾아낸 8μs 차이의 동시성 버그

·2026.02.20 02:00

strace로 mkdirat 경쟁을 잡아, 디렉토리 생성 버그의 원인을 찾아냈다.

shaka-packager로 영상을 DASHHLS 포맷으로 패키징하던 중, 여러 입력 파일을 동시에 처리할 때만 간헐적으로 실패하는 버그가 발생했다. 로그에는 Cannot open file to write만 남아 있었고, 원인은 보이지 않았다.

디스크·메모리 부족, 파일 디스크립터 부족, 특정 영상 문제, 버전 문제를 차례로 배제한 뒤, 동시성 문제를 의심하고 strace로 파일 관련 시스템콜을 추적했다. -ff로 스레드별 로그를 분리하고, -tt마이크로초 단위 타임스탬프를 남겨 성공/실패 케이스를 비교했다.

실패 케이스를 보면 openat으로 출력 파일을 여는 단계까지 가지 못했고, 그 직전에 mkdiratEEXIST로 실패하고 있었다. 두 스레드가 거의 동시에 같은 출력 디렉토리를 만들려고 들어가면서, 불과 8μs 차이로 한 스레드가 먼저 디렉토리를 생성했고 다른 스레드가 EEXIST를 받았다.

문제의 코드는 디렉토리 생성 전에 is_directory()로 존재 여부를 확인한 뒤, 없으면 std::filesystem::create_directories()를 호출하는 구조였다.

  • create_directories()는 새로 만들면 true
  • 이미 존재하면 false지만 ec는 비어 있을 수 있음
  • 그런데 코드는 반환값만 보고 false를 에러로 처리했다

즉, 두 스레드가 동시에 진입하면 한 스레드는 정상 통과하지만, 다른 스레드는 디렉토리가 이미 존재하는 정상 상황을 실패로 오인해 openat까지 가지 못하고 종료했다. 결국 create_directories()ec를 확인하지 않는 처리와 is_directory()-mkdirat 사이의 경쟁 조건이 겹쳐 생긴 버그였다.

해결은 명확했다. 근본적으로는 create_directories()의 에러 처리 방식을 고쳐야 하고, 당장 회피하려면 패키저 실행 전에 출력 디렉토리를 미리 생성해 두면 된다. 그 결과 이후 패키징은 안정적으로 성공했다.

로그 한 줄만 보면 보이지 않던 문제였지만, strace로 시스템콜 수준까지 내려가자 정확히 어디서 무엇이 실패했는지 보였고, 소스 코드의 실제 결함 지점까지 빠르게 도달할 수 있었다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.