libbimmodel.so null pointer in mergingByExternalId — TBB worker thread
RCA: SIGSEGV in BimModel::mergingByExternalId
Error Log#
[120987.90] | Received fatal signal: SIGSEGV(11) PID: 64
***** SIGNAL SIGSEGV(11)
******* STACKDUMP *******
stack dump [1] libg3log.so+0x15d0b
stack dump [2] libc.so.6+0x42520
stack dump [3] libbimmodel.so : cupix::bim_model::v3::BimModel::mergingByExternalId(...)+0x1cf
stack dump [4] libbimmodel.so : cupix::bim_model::v3::BimModel::load(...)+0xbd3
stack dump [5] libbimmodel.so : cupix::bim_model::BimModelFactory::createFromBimModelJson(...)+0x87e
stack dump [6] libbimdeviationmodel.so+0x11ac14
stack dump [7] libbimdeviationmodel.so+0x11b83d
stack dump [8] libtbb.so.12+0x303c3
stack dump [9] libtbb.so.12+0x2abf7
stack dump [10] libc.so.6+0x94ac3
stack dump [11] libc.so.6 clone+0x44
Exiting after fatal event (FATAL_SIGNAL). Fatal type: SIGSEGV
Impact#
- Service:
cupixworks-sitetrack-instance - Team: tpc
- 발생 횟수: 1
- 최초 발생: 2026-04-16T06:33:09.976Z
- 최근 발생: 2026-04-16T06:33:09.976Z
Root Cause Summary#
@cupix-compute/site-track 네이티브 C++ 라이브러리(libbimmodel.so)의 BimModel::mergingByExternalId() 메서드에서 SIGSEGV(segmentation fault)가 발생했습니다. 이 크래시는 TBB(Threading Building Blocks) worker thread에서 발생했으며, BimModelFactory::createFromBimModelJson()을 통해 BIM 모델 JSON을 로드하고 external ID 기반으로 BIM 요소를 병합하는 과정에서 null pointer dereference 또는 잘못된 메모리 접근이 일어난 것으로 판단됩니다. Sitetrack 16458 (team: tpc, job: 1017917)의 BIM validation 처리 중 발생했으며, 메인 thread(121660)에서 processSiteInsight()와 loadBimProgress()가 정상적으로 338개의 progress 항목을 로드한 직후 TBB worker thread(120987)에서 크래시가 발생했습니다. 크래시 지점이 사전 컴파일된 네이티브 .so 라이브러리 내부이므로, JavaScript 레이어에서의 직접적인 코드 수정은 불가능합니다.
Technical Analysis#
Code Path#
- Entry point:
sitetrack-service.ts:87—run()메서드에서 sitetrack 처리 시작 sitetrack-service.ts:101—executeBimValidator(cpSitetrack)호출sitetrack-service.ts:201-227—executeBimValidator()에서 child process 관리자를 통해 네이티브 모듈 실행sitetrack.process.ts:37-42— child process에서SiteTrack네이티브 모듈 인스턴스 생성 및validator.process()호출- Failure point:
libbimmodel.so—BimModel::mergingByExternalId()에서 SIGSEGV
실행 흐름 (sitetrack-service.ts:201-227):
// packages/cupix-sitetrack-master-agent/src/sitetrack-service.ts:201-227
private executeBimValidator = async (cpSitetrack: CPSitetrack): Promise<void> => {
logger.info('Sitetrack::executeBimPointsValidator | begin - sitetrack.id: %d', cpSitetrack.id);
this.logManager.watchLogFile(Constants.DefaultWorkspacePath);
await this.bimProcessManager.initialize();
const params: ProcessParams = {
options_filepath: cpSitetrack.pointsValidatorOptionsFilePath,
request_file_path: cpSitetrack.pointsValidatorRequestFilePath,
result_dir_path: cpSitetrack.bimValidatorResultDirPath,
// ... environment params
};
await this.bimProcessManager.execute(params);
await this.bimProcessManager.stop();
};
Child process에서 네이티브 모듈 호출 (sitetrack.process.ts:28-57):
// packages/cupix-sitetrack-master-agent/src/process/sitetrack.process.ts:35-42
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(); // ← C++ 네이티브 코드 진입, 이후 SIGSEGV 발생
} catch (error) {
// SIGSEGV는 try-catch로 잡히지 않음 — 프로세스 자체가 종료됨
}
});
네이티브 라이브러리 내부 크래시 경로:
validator.process() 호출 후 C++ 네이티브 코드가 실행되며, 내부적으로 다음 호출 스택을 거칩니다:
libbimdeviationmodel.so— BIM deviation 모델 로딩 시작 (TBB parallel task로 dispatch)BimModelFactory::createFromBimModelJson()— JSON 파일에서 BIM 모델 데이터 파싱BimModel::load()— BIM 모델을 메모리에 로드BimModel::mergingByExternalId(const std::set<std::string>&)— external ID 집합을 기반으로 BIM 요소를 병합하는 중 SIGSEGV 발생
스택 프레임 [8-9]에 libtbb.so.12가 있으므로, 이 작업은 TBB worker thread에서 병렬 처리 중이었습니다. Thread ID 120987(크래시 thread)과 121660(메인 processing thread)이 동시에 실행 중이었습니다.
child process 에러 처리 (child-process.manager.ts:107-120):
// packages/base/src/manager/child-process.manager.ts:107-120
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));
});
SIGSEGV 발생 시 child process가 exit code 11로 종료되고, ChildProcessManager가 이를 감지하여 "Process exited with code 11" 에러를 전파합니다. 그러나 SIGSEGV 자체가 네이티브 코드 내부의 메모리 접근 위반이므로 JavaScript 레이어에서는 사전에 방어할 수 없습니다.
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-sitetrack-instance @agent.hostname:ac93446767ec
Time range: 2026-04-16T06:33:00Z to 2026-04-16T06:34:00Z
이벤트 타임라인 (container: ac93446767ec, sitetrack 16458):
| 시간 (KST) | Thread | 이벤트 |
|---|---|---|
| 15:33:08 | main | `Sitetrack::validateForgeUrns |
| 15:33:08 | main | `ForgeUrnValidator::validateForgeUrns |
| 15:33:08 | main | `Sitetrack::executeBimPointsValidator |
| 15:33:09 | 121660 | cupix::bim_algorithm::BimValidator::processSiteInsight() start. |
| 15:33:09 | 121660 | cupix::bim_deviation_model::model_loader::loadBimProgress() start. |
| 15:33:09 | 121660 | loadBimProgress() end. elapsed: 0.002, # of bimProgress: 338 |
| 15:33:09 | 120987 | Received fatal signal: SIGSEGV(11) PID: 64 |
| 15:33:09 | main | `ChildProcessManager::setupEventHandlers |
| 15:33:09 | main | `ChildProcessManager::setupEventHandlers |
| 15:33:09 | main | Process exited with code 11 (x2) |
| 15:33:10 | main | `Sitetrack::terminateService |
핵심 관찰:
- 메인 C++ thread(121660)에서
loadBimProgress()는 338개 항목을 성공적으로 로드 완료 (elapsed: 0.002s) - TBB worker thread(120987)에서
BimModel::mergingByExternalId()실행 중 거의 동시에 SIGSEGV 발생 - 두 thread가 동시에 BIM 모델 데이터에 접근하고 있었으며, TBB 병렬 처리가 크래시의 컨텍스트
14일 내 동일 크래시 검색:
service:cupixworks-sitetrack-instance status:error "SIGSEGV"
Time range: 2026-04-02T00:00:00Z to 2026-04-16T23:59:59Z
결과: 1건만 발견 — 이번 건이 유일한 발생입니다.
동일 시간대 다른 sitetrack instance (container: 663dd3f41e93, sitetrack 16459):
service:cupixworks-sitetrack-instance "16459"
Time range: 2026-04-16T06:30:00Z to 2026-04-16T06:35:00Z
Sitetrack 16459는 별도 컨테이너에서 정상 완료됨 (executeBimPointsValidator | end - sitetrack.id: 16459 at 15:34:04). 크래시는 sitetrack 16458의 컨테이너에 격리됨.
Fix Recommendation#
즉시 조치 (Critical)#
이 크래시는 사전 컴파일된 네이티브 라이브러리(libbimmodel.so) 내부에서 발생하므로, JavaScript 레이어에서 직접 수정할 수 없습니다. @cupix-compute/site-track 패키지를 관리하는 C++ 개발팀(TPC 팀)에 다음 정보와 함께 이슈를 전달해야 합니다:
- 크래시 스택:
BimModel::mergingByExternalId()at offset+0x1cf - TBB worker thread(120987)에서 발생, 메인 thread(121660)는
loadBimProgress()완료 직후 - Sitetrack 16458, Job 1017917, team
tpc, userehenry@wdfinc.net - BIM progress 항목 수: 338개
단기 개선 (1주 이내)#
-
@cupix-compute/site-track네이티브 라이브러리 디버그 빌드: C++ 팀이libbimmodel.so의mergingByExternalId()메서드에서 external ID 집합을 순회하며 BIM 요소를 조회할 때, 해당 요소가 없는(null pointer) 경우에 대한 방어 코드를 추가해야 합니다.std::set<std::string>인자의 각 external ID가 BIM 모델 내 유효한 요소에 매핑되는지 검증 필요. -
입력 데이터 보존:
sitetrack-service.ts의executeBimValidator()호출 전에bim_validator_request.json과bim_progress.json파일을 별도 디렉토리에 백업하여, 크래시 재현 시 동일 입력 데이터로 테스트할 수 있도록 합니다. -
Child process exit code 11 전용 에러 처리:
child-process.manager.ts:107-120에서 exit code 11(SIGSEGV)를 별도로 처리하여, 의미 있는 에러 메시지와 함께 크래시 덤프 수집을 트리거할 수 있도록 개선합니다.
장기 개선 (재발 방지)#
-
TBB thread safety 검토:
BimModel::load()→mergingByExternalId()경로에서 TBB 병렬 처리 시 shared data structure에 대한 동시 접근이 안전한지 검토. TBB가 여러 BIM 모델을 병렬 로드할 때 공유 상태에 대한 race condition 가능성. -
Core dump 수집 자동화: ECS task 정의에서 core dump 생성을 활성화하고, S3에 자동 업로드하여 네이티브 크래시 디버깅을 지원합니다.
-
네이티브 모듈 AddressSanitizer 빌드: 개발/QA 환경에서 ASan이 활성화된 빌드를 사용하여, 메모리 접근 위반을 사전에 탐지합니다.
Monitoring#
- SIGSEGV 재발 감시:
service:cupixworks-sitetrack-instance status:error "SIGSEGV"
- Child process 비정상 종료 감시 (exit code != 0):
service:cupixworks-sitetrack-instance status:error "Process exited with code"
- BIM validation 실패율 추적:
service:cupixworks-sitetrack-instance "executeBimPointsValidator" ("error" OR "failed")
Risk Assessment#
- Risk level: medium
- 예상 복잡도: critical — 네이티브 C++ 라이브러리 내부 버그이며, JavaScript 레이어에서는 직접 수정 불가. C++ 팀의
libbimmodel.so디버깅 및 수정이 필요함. 다만 14일 내 1건 발생으로 빈도는 낮음.