Process exited with code 6
RCA: Process exited with code 6
Overview#
What Happened#
2026-06-24 KST 오후, cupixworks-sitetrack-instance (sitetrack master agent) 가 fork 한 child process 가 종료 시점에 exit code 6 으로 죽었다. 16분간 4회 발생했으며, 부모 프로세스의 Sitetrack::terminateService 가 grace timer 를 시작한 직후 child 의 비정상 종료를 감지해 error 로그를 남겼다. BIM mesh validation 작업의 메인 처리는 완료된 뒤 cleanup/shutdown 단계에서 발생한 것으로 보인다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | Error (synthesized by ChildProcessManager) |
| exception.message | Process exited with code 6 |
| top_frame | packages/base/src/manager/child-process.manager.ts:115 |
| runtime | Node.js child process running native C++ binding @cupix-compute/site-track |
| env | production, us-west-2 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| dprconstruction (sitetrack-master-agent) | 4 | sitetrack job 들이 종료 시점에 비정상 exit — 사용자 가시적 실패 여부는 job state 확인 필요 |
job 별 영향(retry/실패 처리)은 JobManager.updateCompleteActionJob 호출 여부에 따라 달라지며, 본 RCA 시점에서는 확정할 수 없다 (uncertain — needs verification).
Timeline#
- 2026-06-24 16:06 KST — 첫 발생 (
first_seen) - 2026-06-24 16:18 KST — native BIM 처리 단계에서 다수 warn (
Unsupported firmware version detected! - Camera: Insta360 X5, version: v1.6.18_build1,Invalid Geometry / Failed to decode geometry buffer) - 2026-06-24 16:21–16:22 KST —
cupix::bim_algorithm::SiteInsights::*단계의 info 로그가 정상적으로 종료 (elapsed: ...) - 2026-06-24 16:22:27 KST —
Sitetrack::terminateService | force shutdown after 10 seconds(info) 직후 동일 초에 child process 가code: 6으로 종료,ChildProcessManager::setupEventHandlers | Child process closed및Child process exited가 error 로그로 기록됨 (last_seen) - 2026-06-24 (RCA 시점) — RCA 작성
Error Log#
Process exited with code 6
대표 발생 시점 (2026-06-24 16:22:27 KST) 의 인접 로그:
2026-06-24 16:22:27 info Sitetrack::terminateService | force shutdown after 10 seconds
2026-06-24 16:22:27 error Process exited with code 6
2026-06-24 16:22:27 error Process exited with code 6
2026-06-24 16:22:27 error ChildProcessManager::setupEventHandlers | Child process exited
2026-06-24 16:22:27 error ChildProcessManager::setupEventHandlers | Child process closed
2026-06-24 16:22:26 info [104365.31] | cupix::filterInterestedBimMeshes_() end. elapsed: 0
Impact#
- Service:
cupixworks-sitetrack-instance - Team: dprconstruction
- 발생 횟수: 4
- 최초 발생: 2026-06-24 16:06 KST
- 최근 발생: 2026-06-24 16:22 KST
Root Cause Summary#
Child process 가 IPC shutdown 메시지로 graceful cleanup 을 마치고 종료하는 정상 경로에서는 process.exit(0) 또는 process.exit(1) 만 호출된다 (packages/base/src/process/base.process.ts:94,97). 그러나 실제 child 의 exit code 는 6 으로, 이는 TS 레이어 어디에서도 만들어지지 않는 값이다. 따라서 종료 원인은 child 가 임베드한 native C++ 바인딩 @cupix-compute/site-track (SiteTrack.process() — packages/cupix-sitetrack-master-agent/src/process/sitetrack.process.ts:42) 내부에서 process-level abort 또는 명시적 exit(6) 호출이 발생한 것이다. 작업 본체 (BIM mesh filtering, SiteInsights) 가 완료된 뒤 bimProcessManager.stop() 시점에 발생한 점, 그리고 부모가 같은 초에 terminateService grace timer 를 시작한 점으로 미루어 종료/cleanup 경로에서 native 라이브러리의 정리 (소멸자, 리소스 해제) 가 비정상 종료한 것으로 보인다. Node.js 내장 exit code 6 ("Non-function Internal Exception Handler") 가능성도 있으나 BaseProcess 가 uncaughtException 핸들러를 비함수로 설정하지 않으므로 그 경로일 가능성은 낮다 (uncertain — needs verification).
Technical Analysis#
Code Path#
- Entry point:
packages/cupixworks-sitetrack-master-agent/src/sitetrack-service.ts:201(executeBimValidator) - IPC fork:
packages/base/src/manager/child-process.manager.ts:74(fork(actualScriptPath, ...)) - Child main:
packages/cupix-sitetrack-master-agent/src/process/sitetrack.process.ts:42—validator.process()(native call) - Parent shutdown trigger:
packages/cupix-sitetrack-master-agent/src/sitetrack-service.ts:224—await this.bimProcessManager.stop() - Failure point: child process 종료 시점 —
ChildProcessManager::setupEventHandlers | Child process closed에서code=6, signal=null을 받아 부모 측에서Error('Process exited with code 6')을 합성 (packages/base/src/manager/child-process.manager.ts:107-117)
부모 측 child close 처리:
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);
});
Child 측 graceful shutdown 경로 (여기서는 6 을 만들지 않는다):
if (message.type === 'shutdown') {
console.log('BaseProcess::handleMessage | Received shutdown message, cleaning up...');
this.sendSuccess(message.id, { shutting_down: true });
try {
await this.cleanup();
process.exit(0);
} catch (error) {
console.error('BaseProcess::handleMessage | Error during shutdown cleanup:', error);
process.exit(1);
}
return;
}
Child 의 작업 본체 — native SiteTrack 호출:
return new Promise((resolve, reject) => {
try {
const validator = new SiteTrack();
validator.set_options_filepath(params.options_filepath!);
validator.set_request_filepath(params.request_file_path!);
validator.set_output_dirpath(params.result_dir_path!);
validator.process();
this.log('SitetrackProcess::execute | Sitetrack processing completed successfully');
resolve({ success: true });
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const errorStack = error instanceof Error ? error.stack : undefined;
// ...
reject(error);
}
});
부모 측 정상 흐름:
cpSitetrack.setStat({ sitetrack_started_at: new Date(), sitetrack_version: this.bimProcessManager.getVersion() });
await this.bimProcessManager.execute(params);
await this.bimProcessManager.stop(); // 여기서 IPC shutdown 메시지 전송, child 가 cleanup 후 exit(0)/exit(1) 해야 함
cpSitetrack.setStat({ sitetrack_finished_at: new Date() });
기대 동작: bimProcessManager.stop() 이후 child 는 process.exit(0) 으로 종료되어야 하며, ChildProcessManager 의 close 핸들러는 정상 종료 (code=0) 로 받아야 한다.
실제 동작: child 가 code 6 으로 종료하여 부모는 이를 error 로 간주하고 rejectAllPending(new Error('Process exited with code 6')) 호출.
Log Evidence#
사용된 Datadog 쿼리 (클러스터 파일의 URL 그대로):
service:cupixworks-sitetrack-instance status:error @environment:production "Process exited with code 6"
부가 컨텍스트 수집을 위한 쿼리:
service:cupixworks-sitetrack-instance status:(warn OR error)
핵심 로그 시퀀스 (원문):
2026-06-24 16:22:27 info Sitetrack::terminateService | force shutdown after 10 seconds
2026-06-24 16:22:27 error Process exited with code 6
2026-06-24 16:22:27 error ChildProcessManager::setupEventHandlers | Child process exited
2026-06-24 16:22:27 error ChildProcessManager::setupEventHandlers | Child process closed
2026-06-24 16:22:26 info [104365.31] | cupix::filterInterestedBimMeshes_() end. elapsed: 0
2026-06-24 16:22:26 info [104365.31] | cupix::filterInterestedBimMeshes_() start.
2026-06-24 16:22:25 info [104362.49] | cupix::bim_algorithm::SiteInsights::recoverFarMeshes() start.
2026-06-24 16:22:23 info [104417.68] | cupix::bim_algorithm::filteringBimMeshesByDistance() start.
종료 직전 native 측에 명시적 fatal/abort 로그는 잡히지 않았다. 부수적으로 Invalid Geometry(0): Failed to decode geometry buffer, Invalid OTG header - Unexpected zero length CDN resource received warn 다수가 16:21:48-49 KST 에 관찰되었으나, 이는 Forge/Autodesk CDN 에서 일부 mesh 데이터를 정상 로드하지 못한 것으로 child 종료 시점과는 약 38-39 초 차이가 있다.
부모 측 close 시 signal 이 null (즉 SIGKILL/SIGTERM 등 외부 신호가 아닌 process 가 자체 exit(6) 호출). 이는 위 가설 — native lib 가 process-level exit 을 자체적으로 호출 — 과 일치한다.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | Native @cupix-compute/site-track 라이브러리가 cleanup/소멸자 경로에서 exit(6) 또는 abort 호출 |
TS 레이어 어디서도 process.exit(6) 호출 없음 (Grep 결과 0건); BaseProcess shutdown 경로는 exit(0)/exit(1) 만 사용; child close signal=null 로 외부 시그널 아님; 발생 시점이 main 작업 종료 직후 (bimProcessManager.stop() 라인) |
native 로그에서 명시적 abort 메시지 부재 (debug/silly 레벨 확인 필요) | Confirmed (most likely) |
| H2 | Parent 가 timeout 으로 child 를 SIGKILL — ChildProcessManager::sendMessage 의 executeTimeoutMs 초과 |
manager/child-process.manager.ts:213-225 에 timeout 시 SIGKILL 분기 존재 |
SitetrackProcessManager 생성 시 executeTimeoutMs 옵션을 넘기지 않음 (manager/sitetrack-process.manager.ts:11) — 타임아웃 미설정; child close signal 이 null 이라 SIGKILL 흔적 없음 |
Rejected |
| H3 | Sitetrack::terminateService 의 grace timer (ForcedShutdownTimeout) 가 child 를 종료시킴 |
terminateService 가 같은 초에 로그됨 |
해당 timer 는 부모 자체에 대해 process.exit(1) 호출 (sitetrack-service.ts:54) 이며 child 에 SIGKILL 을 보내지 않음; child exit code 가 6 이지 1 이 아님; timer 는 10 초 후 발화이므로 같은 초에 발화 불가 |
Rejected |
| H4 | Node.js 내장 exit code 6 ("Non-function Internal Exception Handler") | TS 코드 어디에도 6 이 생성되지 않으므로 후보 | BaseProcess.setupMessageHandlers 에서 process.on('uncaughtException', non-function) 같은 패턴 없음; uncaughtException 핸들러 자체를 등록하지 않음 |
Rejected (uncertain — needs verification) |
| H5 | Forge OTG / mesh decode 실패로 인한 처리 중단 | 16:21:48-49 KST 의 Failed to decode geometry buffer, Invalid OTG header warn 다수 |
child 가 38-39 초간 정상적으로 추가 작업 (filterInterestedBimMeshes_, SpatialOccupancyGrid::construct) 을 진행했고 모두 정상 종료 (elapsed: 0); 종료 사유로 직접 연결되지 않음 |
Rejected (관련 noise, root cause 아님) |
Fix Recommendation#
즉시 조치 (Critical)#
- Native
@cupix-compute/site-track라이브러리의 종료/소멸자 경로 점검 —packages/cupix-sitetrack-master-agent/src/process/sitetrack.process.ts:37-45의validator객체가 promise resolve 후에도 child process 가 살아남는 동안 native 리소스를 들고 있으며, IPC shutdown 시점에 소멸자에서 abort 가 나는 것으로 추정. site-track 라이브러리 소유 팀이 native 측 cleanup 코드 (특히 GPU/메모리/파일 핸들 해제) 에서assert/abort발생 여부를 확인해야 한다. - 부모 측 close 분류 보정 —
packages/base/src/manager/child-process.manager.ts:107-117. 현재는 child 가 main 작업 성공 후 종료 단계에서 code 6 으로 죽어도 동일하게 error 로그를 남긴다. promise 가 이미 resolve 된 뒤 발생한 close 는 pending 이 없어rejectAllPending이 무의미하지만, error 로그는 그대로 남아 false-positive 알람을 만든다. 이미 resolve 된 작업 후 종료 단계의 비정상 exit 은 warn 으로 분류하는 방향 검토.
단기 개선 (1주 이내)#
- 종료 단계 진단 로그 강화 — child 측
BaseProcess.handleMessage('shutdown')(packages/base/src/process/base.process.ts:88-99) 가cleanup()호출 직전/직후에 console.log 만 사용 중. structured logger 로 변경하고 native 정리 호출 전후의 timestamp 와 메모리/RSS 를 함께 남기면, native abort 직전의 상태를 추적 가능. - Exit code 매핑 —
ChildProcessManager가 known native exit codes (6, 134(SIGABRT), 139(SIGSEGV)) 를 분류해서 별도 error code 로 jobManager 에 전달하면, retry/alert 정책을 분리할 수 있다 (SitetrackProcessManager::execute의ErrorCode.Agent.Default가 현재 일괄 적용 —manager/sitetrack-process.manager.ts:33).
장기 개선 (재발 방지)#
- Native lib 의 abort 안정성 회귀 테스트 — Forge 응답이 정상이고 작업이 완료되는 케이스에서도 종료 단계에 abort 가 나는 시나리오에 대한 통합 테스트 추가.
- IPC 종료 프로토콜 단순화 — 작업 성공 후에는 부모가 SIGTERM 으로 빠르게 종료하고 child 의 abort 가 자식 종료 처리에 영향주지 않게 격리 (성공 분기에서는 close error 무시).
Monitoring#
추가 메트릭/알림:
종료 코드 6 발생 빈도:
sum:logs.hits{service:cupixworks-sitetrack-instance,@message:"Process exited with code 6"}.as_count()
전체 child 비정상 종료 (코드 0 외 모두):
sum:logs.hits{service:cupixworks-sitetrack-instance,@message:"Child process closed"}.as_count()
Forge mesh decode 실패와의 상관관계:
sum:logs.hits{service:cupixworks-sitetrack-instance,@message:"Failed to decode geometry buffer"}.as_count()
알람 임계값: 5분 윈도 내 동일 클러스터 fingerprint 3회 이상 발생 시 alert.
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard (native lib 점검이 필요한 경우 critical)
이유: 작업 본체 (BIM validation) 는 종료 전에 성공적으로 진행된 정황이 있어 사용자 데이터 손상 위험은 낮지만, child 비정상 종료가 jobManager.updateCompleteActionJob 호출 전 promise 체인을 깨는 경우 job 상태가 incomplete 으로 남을 수 있다. native 라이브러리 수정이 필요하면 site-track 팀과의 협업이 필요해 복잡도가 올라간다.