TCPAGENT는 system()이 도는 동안 통째로 얼어 있어 응답도 진행 보고도 못 한다.
그런데 호스트는 소켓에 30초 고정 타임아웃을 걸고, 만료되면 연결 자체를 버렸다.
그래서 35초짜리 컴파일이 "느린 명령"이 아니라 "죽은 에이전트"로 취급됐다.
QEMU는 게스트가 얼어 있어도 계속 돈다. info blockstats의 idle_time_ns로
"작업 중"과 "멈춤"을 구분한다. 실측으로 확인했다: 에이전트가 완전히 벙어리인
동안에도 rd_operations가 7초당 47000씩 증가하고 idle은 0.00s를 유지한다.
- EXEC은 짧은 간격으로 깨어나 감시만 하고 소켓은 절대 안 버린다.
- --idle-timeout(기본 60s)과 --hard-timeout(기본 900s). 후자는 디스크를
안 쓰는 CPU 바운드 멈춤용 백스톱이다.
- 중단은 QEMU 모니터로 Ctrl+C를 주입하고 COMMAND.COM의
"Terminate batch file (Y/N/A)?" 프롬프트에 답한다.
- Ctrl+C는 DOS break check에서만 먹는다. FreeDOS 기본값 BREAK=OFF에서
출력을 파일로 돌린 CPU 바운드 자식은 거기 도달 안 할 수 있다. 그래서
중단은 보장이 아니라 요청으로 다루고, 명령이 안 멈춰도 RESULT를 끝까지
수거해 스트림을 깨뜨리지 않는다.
- ferro-vm abort 추가. 실행 중에도 응답해야 하므로 파이프 서버를 요청당
스레드로 바꿨다.
- 5558 바인딩을 SO_EXCLUSIVEADDRUSE로. Windows의 SO_REUSEADDR는 다른
프로세스가 같은 포트를 잡아 조용히 반쯤 동작하게 만든다.
검증 (QEMU FreeDOS 실측):
- 32.4초 명령 정상 완료 (이전에는 30초에 실패)
- 실행 중 abort가 0.1초에 응답, exit=95로 종료, 부분 출력 1805B 수거,
연결 유지
- pause처럼 디스크를 안 쓰는 명령을 idle 15s로 검출해 중단
시리얼 시절에 있다가 TCP 전환에서 사라진 TODO 3건을 복구한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012PQm6oAvWX4Lp3iSN5AHGT
DOS 콘솔에서 직접 보기 위한 네 가지 수정.
1. 컬러. Open Watcom의 conio.h에는 textattr()이 없고(cprintf/cputs/getch만
제공) 이 FreeDOS 콘솔은 ANSI 이스케이프도 해석하지 않는다. 그래서 cprintf가
줄을 배치하게 두고 -- 스크롤을 알아서 처리한다 -- 방금 쓴 셀의 VGA 속성
바이트만 다시 칠한다. 커서가 그 줄 다음 행의 0열에 있다는 점을 이용해
스크롤을 직접 추적하지 않고 대상 셀을 찾는다. 줄바꿈된 긴 줄도 처리한다.
2. GET, HASH, LIST, READ, WRITE, QUIT, 미지원 명령을 로깅한다. 이전에는
EXEC과 PUT만 보였다. PING은 wait-ready가 초당 두 번 폴링하므로 제외한다.
LIST는 잘림 여부를, PUT은 short write를 구분해 남긴다.
3. put_path가 채워지기만 하고 쓰이지 않아 PUT 완료 줄에 경로가 없었다.
완료 경로가 둘(길이 0, 본문 수신 완료)이라 put_finished()로 합쳤다.
4. 틱->초 변환이 1.1% 빨랐다. BIOS 틱은 18.2065Hz이므로 delta/18이 아니라
delta*549/100 (하루치 틱에도 32비트를 넘지 않는다) 을 쓴다.
REBUILD.BAT을 추가한다. BUILD.BAT은 현재 디렉터리에서 wmake만 실행하는데
호스트가 exec으로 부를 때의 시작 디렉터리가 거기가 아니다.
QEMU FreeDOS에서 Open Watcom C++16으로 빌드하고(no warnings, -we 활성)
콘솔 스크린샷으로 색상, 줄바꿈 색칠, 명령별 로그를 확인했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012PQm6oAvWX4Lp3iSN5AHGT