그동안 미추적으로 쌓여 있던 인수인계 문서를 정리해 올린다. 260903 Door 인터락 현장검증 가이드 / 파워캘 3000W 오적용 환산 260907 Arc 출사 파라미터 시각화 / LaserFrequency 단위계통 / NRE 위험구간 점검 / 레시피화면 사용설명서 260915 레시피화면 작업매뉴얼 260916 PTOP 프로그램 사용설명서 / 자동운전 전환 사전점검 현장용 작업 중 임시본(_backup)은 제외했다.
159 lines
7.9 KiB
Markdown
159 lines
7.9 KiB
Markdown
# NRE / 크래시 위험 구간 점검
|
|
|
|
- 작성 : 2026-09-07
|
|
- 계기 : 출사 미지원 객체(Ellipse/Rectangle/Roi) NRE 방어(`ISSUE-260907-01`) 적용 후,
|
|
같은 유형이 더 있는지 전수 확인 요청.
|
|
- 성격 : **점검 목록 전용. 소스 미수정. 현장 검증 미실시.**
|
|
- 표기 : 🟩 소스 확인 / 🟦 현장 기록 / 🟨 미확보·판정 불가
|
|
|
|
## 점검 범위와 한계
|
|
|
|
| 구분 | 내용 |
|
|
|---|---|
|
|
| 포함 | `Machines/ILSOS_PrismaticRD_PTOP/**`, `WeldingComponents/WeldingCommon/Sequences/**` |
|
|
| 제외 | AuroraVision, LASA GUI(Canvas·DrawTools), AuroraDevices 하위 대부분, Aurora 프레임워크 |
|
|
| 방법 | 패턴 검색(`FirstOrDefault`/`First()`/`[0]`/`as`/인덱서) 후 해당 라인 전후 확인 |
|
|
| 한계 | 정적 분석. 런타임 재현·디버깅 없음. 제외 범위에 같은 유형이 더 있을 수 있음 |
|
|
|
|
---
|
|
|
|
## 0. 선행 확인 — 예외가 실제로 프로그램을 종료시키는가
|
|
|
|
🟩 우리 소스에 **전역 예외 핸들러가 없습니다.**
|
|
`DispatcherUnhandledException` / `AppDomain.CurrentDomain.UnhandledException` /
|
|
`UnobservedTaskException` / `SetUnhandledExceptionMode` 검색 결과 **0건**.
|
|
|
|
🟩 `ILSOS_PrismaticRD_PTOP.csproj` → `OutputType=library`.
|
|
즉 실행 주체는 **Aurora.exe** 이고 저장소에 소스가 없습니다.
|
|
|
|
🟨 따라서 아래 항목이 **실제로 프로세스를 종료시키는지는 판정할 수 없습니다.**
|
|
- Aurora.exe 가 전역 핸들러를 걸어 두었는지 미확인
|
|
- Aurora `SequenceBuilder` 가 노드 실행을 try/catch 로 감싸는지 미확인
|
|
(`sb.OnForceError(...)` 훅이 존재하므로 **잡을 가능성은 있음**)
|
|
|
|
> **이 문서는 "NRE 가 발생할 수 있는 지점" 목록입니다.**
|
|
> "여기서 프로그램이 죽는다" 로 읽지 마십시오. 종료 여부는 별도 확인 필요.
|
|
|
|
---
|
|
|
|
## A. 널 체크 없이 즉시 역참조 — 위험도 최상
|
|
|
|
### A-1. `SeqComponentTeachingRun.cs:456-459` 🟩
|
|
|
|
```csharp
|
|
var power = Status.GetProcessingWeldingData().UploadProcessDatas
|
|
.Where(data => data.DataName == $"Power_{SlotNo}_{_SequenceSetting.LastPageNo}")
|
|
.FirstOrDefault();
|
|
power.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower1
|
|
+ ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower2; // ← power == null 이면 NRE
|
|
|
|
var velocity = ...Where(data => data.DataName == $"Velocity_{SlotNo}_{...}").FirstOrDefault();
|
|
velocity.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].MarkSpeed; // ← 동일
|
|
```
|
|
|
|
- `DataName` 을 `SlotNo` + `LastPageNo` 로 **문자열 조합**해 찾습니다.
|
|
- 그 조합이 `UploadProcessDatas` 에 없으면 `FirstOrDefault()` 가 `null` 을 반환합니다.
|
|
- **페이지 수가 늘거나 슬롯 번호 체계가 바뀌면 즉시 발생**합니다.
|
|
- 실제 운전 경로(Manual 티칭런)라 재현 가능성이 목록 중 가장 높습니다.
|
|
|
|
### A-2. `SeqEventQTest.cs:142-145` 🟩 — 3중 위험
|
|
|
|
```csharp
|
|
FovInfo _fovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault();
|
|
_PatternAgent = FovPatternAgentManager.GetAgent(_fovInfo.ToSubSysInfo()); // ① _fovInfo null → NRE
|
|
List<PatternInfo> patterns = _PatternAgent.GetMainPatterns(_fovInfo); // ② agent null → NRE
|
|
_PatternInfo = patterns[0]; // ③ 빈 리스트 → IndexOutOfRange
|
|
```
|
|
|
|
### A-3. `SeqAutoRunPrismatic.cs:1101-1104` 🟩
|
|
|
|
A-2 와 동일 패턴 + `_Patterns[_InitParam.VisionRecipeNo]` 인덱스 무검증.
|
|
|
|
> 🟩 **참고 — 올바른 패턴이 같은 파일에 이미 있습니다.**
|
|
> `SeqAutoRunPrismatic.cs:743-745` 는 `_PatternResult?.Results?.FirstOrDefault()` 로
|
|
> 널 조건 연산자를 쓰고 이후 `if (baseResult != null)` 까지 확인합니다.
|
|
> A-2 · A-3 만 이 방어가 빠져 있습니다.
|
|
|
|
---
|
|
|
|
## B. `as` 캐스팅 결과를 가드 없이 보관 — 지연 발화형
|
|
|
|
캐스팅 실패 또는 키 부재 시 조용히 `null` 이 되고, **한참 뒤 그 필드를 사용하는 시점**에 터집니다.
|
|
발생 위치와 원인 위치가 달라 추적이 어렵습니다.
|
|
|
|
| 위치 | 대상 | 🟩 |
|
|
|---|---|---|
|
|
| `SeqAutoRunPTOP.cs:291` | `_SystemParameter` | 🟩 |
|
|
| `Views/Main/UCMainAutoRunViewModel.cs:95-97` | `_SystemParameter`, `_Scanner`, `_Plc` | 🟩 |
|
|
| `Views/Main/UCMainAutoRunViewModel.cs:472, 505` | `_SystemParameter` 재대입 | 🟩 |
|
|
| `SeqTestRun.cs:472` | `_IOLaser` | 🟩 |
|
|
| `SeqComponentTeachingRun.cs:179` | `_SequenceSetting` | 🟩 |
|
|
| `Monitoring/SeqStatusMonitor.cs:60` | `_SequenceSetting` | 🟩 |
|
|
| `SeqAutoRunPrismatic.cs:1050` | `SystemSetting` | 🟩 |
|
|
| `EquipmentSetup.cs:90, 199, 240, 342` | `EquipmentInfo` | 🟩 |
|
|
| `EquipmentSetup.cs:129, 133` | `IODevice`, `PLCControllerPTOP` | 🟩 |
|
|
| `Recipes/RMSHandlerForPTOP.cs:52-53` | `_plc`, `_RmsSetting` | 🟩 |
|
|
|
|
대부분 **초기화 구간**이라 정상 구성에서는 성공합니다.
|
|
위험은 "설정 키 이름 변경 / 디바이스 등록 누락 / 타입 교체" 시 **즉시 실패하지 않는다**는 점입니다.
|
|
|
|
🟩 **예외 — 이미 방어된 곳** : `SeqAutoRunPTOP.cs:1140, 1252` 의 `LaserInterlockSetting` 은
|
|
`LaserAngleOffsetSelector.Select()` 안에서 `setting != null` 삼항 처리로 방어됩니다.
|
|
|
|
---
|
|
|
|
## C. 인덱스 무검증 — NRE 는 아니나 동일하게 종료 요인
|
|
|
|
| 위치 | 위험 | 🟩 |
|
|
|---|---|---|
|
|
| `SeqUploadWeldingList.cs:206` | `SelectedDrawObjectList[0]` — 빈 리스트 | 🟩 |
|
|
| `SeqUploadWeldingList.cs:207-209` | `ScannerParams[ScannerParamID - 1]` — **ID 가 0 이면 인덱스 -1** | 🟩 |
|
|
| `SeqUploadWeldingList.cs:474, 617-631, 719, 1006, 1052, 1152, 1204, 1404, 1605` | `ScannerParams[obj.ScannerParamNo]` 범위 무검증 (배열은 128개 고정 생성) | 🟩 |
|
|
| `SeqWaitWeldOrChangePage.cs:194-195` | `ScannerParams[paramIndex]` | 🟩 |
|
|
| `SeqTestRun.cs:237-238` | `ScannerParams[paramIndex]` | 🟩 |
|
|
| `SeqComponentTeachingRun.cs:457-465` | `ScannerParams[paramIndex]` | 🟩 |
|
|
| `SeqAutoRunPrismatic.cs:1104` | `_Patterns[VisionRecipeNo]` | 🟩 |
|
|
|
|
**`SeqUploadWeldingList.cs:206-209` 주의** — 2026-09-07 적용한 예외처리는
|
|
`FuncLoadDrawObjectScannerParamSelected()` 쪽이라 **이 경로는 여전히 무방비**입니다.
|
|
|
|
---
|
|
|
|
## D. 예외는 안 나지만 값이 오염되는 것 (참고)
|
|
|
|
double 나눗셈이라 예외 대신 `Infinity`/`NaN` 이 조용히 흘러갑니다.
|
|
|
|
| 위치 | 내용 |
|
|
|---|---|
|
|
| `ScannerRTC6.cs:775` · `ScannerRTC5.cs:773` | `32.0 / periodHz` — `periodHz == 0` 이면 `Infinity` → `(uint)` 캐스팅은 정의되지 않은 동작 |
|
|
| `SeqUploadWeldingList.cs:1313-1316` | `ArcRampingInterval == 0` 시 동일 |
|
|
|
|
상세 : [`260907_LaserFrequency_단위계통_분석.md`](260907_LaserFrequency_단위계통_분석.md)
|
|
|
|
---
|
|
|
|
## 우선순위 제안
|
|
|
|
| 순위 | 항목 | 근거 |
|
|
|---|---|---|
|
|
| 1 | **A-1** | 실제 운전 경로(Manual 티칭런) + 조합 문자열 탐색이라 재현 가능성 최상 |
|
|
| 2 | **C 의 `SeqUploadWeldingList.cs:206-209`** | 이번 예외처리가 커버하지 못한 인접 경로 |
|
|
| 3 | **A-2 / A-3** | 비전 경로. Vision 미사용이면 후순위 |
|
|
| 4 | **B** | 개별 수정보다 초기화 구간 일괄 널 가드 + 알람이 적절 |
|
|
| — | **선행** | Aurora.exe / SequenceBuilder 의 예외 처리 정책 확인. 이게 정해져야 "가드 후 어떻게 할지"(스킵 / 알람 / 시퀀스 중단)가 결정됨 |
|
|
|
|
## 조치 시 주의
|
|
|
|
- **조용히 스킵하면 안 되는 경우가 있습니다.** A-1 은 공정 데이터 상신 실패를 뜻하므로,
|
|
널이면 로그만 남기고 넘어가면 **데이터 누락이 은폐**됩니다. 알람 여부를 함께 정해야 합니다.
|
|
- 반대로 이번 `ISSUE-260907-01` 처럼 **원래도 동작하지 않던 경로**는 스킵이 맞습니다.
|
|
- 즉 "널이면 무조건 return" 을 일괄 적용하지 마십시오. 항목마다 판단이 다릅니다.
|
|
|
|
---
|
|
|
|
## 변경 이력
|
|
|
|
| 일자 | 내용 | 비고 |
|
|
|---|---|---|
|
|
| 2026-09-07 | 최초 작성. PTOP + WeldingCommon Sequences 범위 점검 | 소스 미수정 |
|