21.9.3. 안전한 백그라운드 전환 및 시스템 셧다운(Shutdown) 대응
부팅 스크립트(rc.mc_apps)에서 우리의 payload_autodrop start 명령어가 불려 나가는 순간, 터미널(Console) 창에는 환희의 로그가 뜨겠지만 이면에 도사리고 있는 무거운 책임감을 직시해야 한다.
C++ 초급 시절 짜던 데스크탑 main() 함수들은 계산을 끝내면 return 0;를 뱉고 쿨하게 메모리에서 사라진다.
하지만 우리의 PX4 커스텀 모듈은 드론의 심장이 멎을 때까지 영원히 끝나지 않는 무한 루프(while(1) 또는 WorkQueue 스케줄링) 속에서 살아 숨 쉬게 된다.
이 영생의 굴레 속에서 시스템 안정성을 유지하기 위해 우리는 두 가지 치명적인 하급 실수를 방어해야 한다.
- 터미널 장악 (Foreground Blocking): 스크립트가 내 모듈을 실행시켰는데, 내 로직이 콘솔(명령창)을 물고 놔주지 않아서 다음 PX4 앱들이 부팅되지 못하고 전체 시스템이 얼어붙는 현상.
- 좀비화 (Zombie Process): 펌웨어 업데이트나 재부팅을 위해 시스템이 “모두 꺼져라!(Stop)” 라고 셧다운 명령을 내렸는데, 내 모듈이 루프를 탈출하지 못하고 메모리를 물고 늘어지다 결국 커널 패닉(Kernel Panic)을 유발하는 현상.
1. 데몬화(Daemonization): 터미널의 족쇄를 끊다
이 두 가지 비극을 막아주는 마법의 단어가 바로 **데몬화(Daemonization)**다.
PX4 아키텍처에서는 우리가 상속받았던 ModuleBase<T>가 이 마법의 지팡이 역할을 해준다. 개발자가 특별한 쉘 명령(& 커맨드 등)을 붙이지 않아도, ModuleBase의 뼈대를 충실히 따랐다면 모듈은 start 명령어 호출 직후 다음과 같은 섬세한 동작을 자동으로 수행한다.
- 태스크 분리(Task Forking): 새로운 독립 스레드(태스크)를 하나 복제하여 떼어낸다.
- 제어권 반환: 나를 부른 부모 스크립트(
rc.mc_apps)에게 “나 잘 켜졌어!” 라고 즉시0(Success)을 반환하여 스크립트가 다음 명령어로 넘어가게 해 준다. (블로킹 방지) - 입출력 리다이렉션: 원래 타이핑 치던 콘솔창과의 연결을 끊고, 출력되는 모든
PX4_INFO로그들을 uORB 로깅망이나 SD 카드 파일(ULog)로 은밀하게 리다이렉트 시켜버린다.
이 고결한 डे몬(Daemon)으로 승격하기 위해, 코드 내부적으로 표준 입출력 파이프를 끊어내는 디테일한 I/O 리다이렉션 기법을 다음 21.9.3.1.1 장에서 파헤쳐보겠다.
2. 우아하게 죽는 법 (Graceful Shutdown)
태어나는 것보다 죽는 것이 더 중요하다.
조종사가 터미널에 payload_autodrop stop을 타이핑하거나, 혹은 시스템이 강제 리부팅 시그널을 돌리면 PX4 커널은 우리 모듈의 custom_command() 또는 소멸자 쪽에 종료 신호(Kill Signal)를 때린다.
이때 우리의 Run() 함수는 자비 없이 돌아가는 무한 스케줄링 쳇바퀴(WorkQueue) 안에서 어떻게 스스로 목숨을 끊어야 할까?
// [종료(Stop) 시그널을 받을 때 호출되는 약속된 함수]
int PayloadAutoDrop::custom_command(int argc, char *argv[]) {
// ...
if (!strcmp(argv[0], "stop")) {
// 1. [핵심] 스케줄링의 심장 고리를 끊어버린다!
ScheduleClear();
// 2. 현재 상태에 상관없이 서보 밸브를 안전하게 강제로 닫아버린다.
close_payload_servo();
PX4_INFO("Payload Module cleanly stopped.");
return 0;
}
// ...
}
이 ScheduleClear() 함수 한 방이 바로 WorkQueue에 예약되어 있던 다음 20ms 뒤의 알람을 영원히 취소해 버리는 권총이다.
루프가 끊어지면, C++ 스코프를 빠져나가며 소멸자가 호출되고, uORB 파편(구독 객체들)이 메모리에서 완벽히 해제(Deallocation)되며 진정한 ’클린 셧다운(Clean Shutdown)’이 완성된다.
이제 데몬의 철학을 마음에 새겼으니, 실제로 C++ 코드상에서 콘솔의 파이프를 끊고 로그의 흐름을 ULog 파일로 비틀어버리는 마법 같은 한 줄, PX4_INFO와 입출력 리다이렉션의 실체를 21.9.3.1.1장에서 목격해 보자.