ES /docs

libalignalgorithm.so SIGSEGV in triangulation — missing null check

RCA: SkatmasterService::runService | error

Overview#

What Happened#

2026-04-27 00:55:53 UTC에 cupixworks-captue-skatmaster-arm-instance 서비스의 ap-southeast-2 리전에서 skatmaster native 프로세스가 SIGSEGV (segmentation fault) 로 크래시하여 SkatmasterService::runService | error가 발생했다. capture 69410 / job 181610 처리 중 Insta360 X5 카메라(firmware v1.10.11_build1)의 영상을 VISLAM triangulation 단계에서 처리하던 중 native C++ 라이브러리(libalignalgorithm.so)가 메모리 접근 위반으로 비정상 종료되었다.

Quick Facts#

Field Value
exception.class SIGSEGV (signal 11)
exception.message exitWithDefaultSignalHandler:226. Exiting due to FATAL_SIGNAL, 11
top_frame libalignalgorithm.so : cupix::align_algorithm::inertial::ComputeVISLAM::triangulatePair(...)
env production, ap-southeast-2

Affected Teams#

Team / Domain Error Count Impact
naylorlove (team_id: 22) 1 capture 69410 / job 181610 처리 실패, 사용자 david.vanwyk@naylorlove.co.nz의 스캔 결과 미생성

Timeline#

  1. 00:11:36ZSkatmasterService::InitServicerunService 시작
  2. 00:11:39Z — 입력 데이터 로드 완료 (video: VID_20260423_105655_00_003.insv, Insta360 X5, 0 panos, 1 video, 0 frames)
  3. 00:11:39Z — firmware 미지원 경고 6회 발생 (Unsupported firmware version detected! - Camera: Insta360 X5, version: v1.10.11_build1)
  4. 00:15:34ZSliding offsets are not monotonic 경고
  5. 00:22:44Zscenes are splitted! - num scenes: 3 — 영상이 3개 scene으로 분할
  6. 00:22:45ZaccBias jumped!, Initialization failed (9 - 24) - BA failed — Bundle Adjustment 초기화 실패
  7. 00:55:39ZSIGSEGV(11) 발생 — native 프로세스 크래시
  8. 00:55:53ZSkatmasterService::forceShutdown, error 로그 기록, ECI 파일 저장

Error Log#

Datadog Logs

text
SkatmasterService::runService | error

Impact#

  • Service: cupixworks-captue-skatmaster-arm-instance
  • 발생 횟수: 1
  • 최초 발생: 2026-04-27T00:55:53.429Z
  • 최근 발생: 2026-04-27T00:55:53.429Z

Root Cause Summary#

Insta360 X5 카메라(firmware v1.10.11_build1)로 촬영된 영상의 VISLAM (Visual-Inertial SLAM) 처리 중 libalignalgorithm.so native 라이브러리의 ComputeVISLAM::triangulatePair() 함수에서 segmentation fault (SIGSEGV) 가 발생했다. 이 firmware 버전은 skatmaster SDK에서 공식 지원하지 않아 6회의 경고가 기록되었으며, 불안정한 센서 데이터(가속도계 바이어스 점프, 비단조 슬라이딩 오프셋)로 인해 Bundle Adjustment 초기화가 실패한 상태에서 triangulation 연산이 진행되면서 유효하지 않은 메모리 참조가 발생한 것으로 판단된다. 이는 native C++ 라이브러리 내부의 방어 로직 부재가 근본 원인이다.

Technical Analysis#

Code Path#

  1. Entry pointskatmaster-service.ts:44 (runService)에서 서비스 실행 시작
applications/agents/packages/cupix-skat-master-agent/src/skatmaster-service.ts:44-65typescript
protected runService = async (): Promise<void> => {
    logger.info('SkatmasterService::runService');
    try {
        await this.skatmasterManager.saveSkatSDKVersion();
        await this.skatmasterManager.loadPreprocessorResult();
        // ...
        await this.skatmasterManager.runSkatMaster();
        await this.skatmasterManager.checkAndCopyForReconstruction();
        await this.skatmasterManager.saveDecodingResultsToEFS();
    } catch (e) {
        logger.error('SkatmasterService::runService | error');
        throw e;
    }
};
  1. Manager orchestrationskatmaster.manager.ts:164-226에서 runSkatMaster() 실행, native 프로세스에 파라미터 전달
applications/agents/packages/cupix-skat-master-agent/src/manager/skatmaster.manager.ts:200-225typescript
this.skatLogManager.watchLogFile(this.skatWorkspacePath);
this._skatProcessResults = await this.execute(params);  // line 204

// ... result handling ...

} catch (e) {
    logger.error('SkatmasterManager::runSkatMaster | end %s', JSON.stringify(e));  // line 223
    throw e;
}
  1. Child process executionchild-process.manager.ts:186-199에서 IPC를 통해 skatmaster native 프로세스에 메시지 전달
applications/agents/packages/base/src/manager/child-process.manager.ts:186-199typescript
async execute<T = unknown>(type: string, data?: unknown, timeoutMs?: number): Promise<T> {
    if (!this.isRunning) {
        await this.start();
    }
    const message: Message = { id: randomUUID(), type, data };
    const effectiveTimeout = timeoutMs ?? this.options.executeTimeoutMs;
    return this.sendMessage(message, effectiveTimeout);
}
  1. Native C++ callskatmaster.process.ts:224에서 this.sceneMapper.process() 호출 시 SIGSEGV 발생
applications/agents/packages/cupix-skat-master-agent/src/process/skatmaster.process.ts:220-230typescript
const startTime = Date.now();
this.sendSkatMessage('logger_debug', 'SkatmasterProcess::execute::sceneMapper | process - begin');
this.sceneMapper.process();  // LINE 224: NATIVE C++ CRASH POINT
this.sendSkatMessage('logger_debug', 'SkatmasterProcess::execute::sceneMapper | process - done');
const endTime = Date.now();
  1. SIGSEGV 감지child-process.manager.ts:107-120에서 child process close 이벤트로 크래시 감지, pending promise reject
applications/agents/packages/base/src/manager/child-process.manager.ts:107-120typescript
this.process.on('close', (code: number | null, signal: string | null) => {
    logger.error('ChildProcessManager::setupEventHandlers | Child process closed', {
        code, signal
    });
    const errorMsg = signal
        ? `Process killed by signal ${signal} (code: ${code})`
        : `Process exited with code ${code}`;
    this.rejectAllPending(new Error(errorMsg));
    this.process = undefined;
    this.emit('close', code, signal);
});
  1. "end undefined" 로그 원인skatmaster.manager.ts:223에서 JSON.stringify(e)는 Error 객체의 non-enumerable 프로퍼티를 직렬화하지 못해 undefined가 출력됨
applications/agents/packages/cupix-skat-master-agent/src/manager/skatmaster.manager.ts:223typescript
logger.error('SkatmasterManager::runSkatMaster | end %s', JSON.stringify(e));
// Error { message: "Process killed by signal SIGSEGV" } → JSON.stringify → "{}" or undefined

Log Evidence#

SIGSEGV 발생 직전 warn 로그에서 native 프로세스의 크래시 스택 트레이스를 확인:

text
Datadog query: service:cupixworks-captue-skatmaster-arm-instance @host.name:0eab47322e3e
Time range: 2026-04-27T00:00:00Z ~ 2026-04-27T01:00:00Z

firmware 미지원 경고 (00:11:39Z, 6회 반복):

text
Unsupported firmware version detected! - Camera: Insta360 X5, version: v1.10.11_build1

센서 데이터 이상 징후 (00:15:34Z ~ 00:22:45Z):

text
Sliding offsets are not monotonic.
scenes are splitted! - num scenes: 3
accBias jumped!
Initialization failed (9 - 24) - BA failed

SIGSEGV 발생 (00:55:39Z):

text
FATAL SIGNAL: SIGSEGV(11)
exitWithDefaultSignalHandler:226. Exiting due to FATAL_SIGNAL, 11

크래시 위치:

text
libalignalgorithm.so : cupix::align_algorithm::inertial::ComputeVISLAM::triangulatePair(...)

에러 전파 로그 (00:55:53Z):

text
[ERROR] SkatmasterManager::runSkatMaster | end undefined
[ERROR] SkatmasterService::runService | error

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 미지원 Insta360 X5 firmware(v1.10.11_build1)로 인한 native 라이브러리 SIGSEGV firmware 경고 6회 발생, BA 초기화 실패, accBias jumped, 최종 triangulatePair()에서 SIGSEGV 크래시. config_works.json에 X5는 지원하나 firmware 버전 호환성은 native SDK 내부에서 관리됨 Insta360 X5 자체는 config_works.json에 지원 목록에 포함됨 Confirmed
H2 영상 파일 손상 또는 비정상 입력 데이터 0 panos loaded, 0 frames loaded는 비정상으로 보일 수 있음 1 video는 정상 로드됨. 영상 파일 자체의 손상을 시사하는 로그 없음. 프로세스는 44분간 정상 실행 후 크래시되었으므로 입력 자체는 유효 Rejected
H3 메모리 부족(OOM)으로 인한 프로세스 크래시 장시간(44분) 실행은 메모리 소모 가능 시그널이 SIGSEGV이며 SIGKILL(9)이 아님. OOM Killer는 SIGKILL을 보냄. 크래시 위치가 특정 함수(triangulatePair)로 명확 Rejected
H4 TBB 멀티스레딩 race condition 크래시 스택에 TBB worker thread 포함 race condition이라면 간헐적으로 다양한 위치에서 발생해야 하나, 이 경우 특정 함수에서 발생. BA 초기화 실패 상태에서의 연산 진행이 더 직접적 원인 Rejected

Fix Recommendation#

즉시 조치 (Critical)#

  1. 에러 직렬화 개선skatmaster.manager.ts:223에서 JSON.stringify(e) 대신 JSON.stringify(e, Object.getOwnPropertyNames(e)) 또는 e instanceof Error ? e.message : JSON.stringify(e) 사용. 동일 패턴이 skatmaster.process.ts:246에서는 이미 올바르게 구현되어 있으므로 이를 참고.

  2. 에러 로그 상세화skatmaster-service.ts:62에서 logger.error('SkatmasterService::runService | error') 에도 에러 객체를 포함하도록 수정. 현재는 에러 내용이 전혀 기록되지 않음.

단기 개선 (1주 이내)#

  1. BA 초기화 실패 시 early termination — native SDK에서 Bundle Adjustment 초기화가 실패한 경우(Initialization failed (9 - 24) - BA failed), 후속 triangulation 연산을 건너뛰고 graceful하게 에러를 반환하도록 native 라이브러리 수정이 필요. 이는 native C++ 코드 변경이므로 SDK 팀과 협의.

  2. 미지원 firmware 처리 강화Unsupported firmware version detected! 경고가 발생했을 때 agent 레벨에서 이를 감지하여 처리를 중단하거나 사용자에게 firmware 업데이트를 안내하는 로직 추가 검토.

장기 개선 (재발 방지)#

  1. Native SDK crash guardsceneMapper.process() 호출을 별도의 sandbox 프로세스에서 실행하여 SIGSEGV가 전체 agent를 다운시키지 않도록 격리. 현재 ChildProcessManager가 이미 fork 기반이므로 크래시 격리는 되어 있으나, 크래시 원인(초기화 실패 상태에서의 연산 진행)을 근본적으로 방지해야 함.

  2. Firmware 호환성 매트릭스 — Insta360 X5의 각 firmware 버전별 호환성을 문서화하고, 미지원 버전 입력 시 처리 전에 reject하는 메커니즘 도입.

Monitoring#

  • SIGSEGV 크래시 빈도 모니터링:
text
service:cupixworks-captue-skatmaster-arm-instance status:warn SIGSEGV
  • Unsupported firmware 경고 추적:
text
service:cupixworks-captue-skatmaster-arm-instance "Unsupported firmware version detected"
  • BA 초기화 실패 빈도:
text
service:cupixworks-captue-skatmaster-arm-instance "Initialization failed" "BA failed"

Risk Assessment#

  • Risk level: low (단일 발생, 특정 firmware 버전에 한정)
  • 예상 복잡도: standard (에러 직렬화 수정은 trivial, native SDK 수정은 SDK 팀 의존)