#tech 수정: 2026-11-01

lwIP tcp_close()가 ERR_MEM을 반환하면: PCB를 보존하고 callback에서 재시도하기

lwIP RAW TCP에서 tcp_close()가 ERR_MEM을 반환하면 미확인 ACK가 있다는 이유만으로 기다리지 말고, 오류 반환 시 PCB가 유효한 상태로 남는지 확인한 뒤 sent 또는 poll callback에서 재시도합니다.

lwIP RAW TCP에서 tcp_close()가 ERR_MEM을 반환하면, 우선 PCB 포인터를 버리거나 같은 loop에서 계속 호출하지 마세요. 공식 API 설명에 따르면 종료에 필요한 메모리를 확보하지 못한 경우이며, 오류가 반환된 PCB는 해제되지 않았으므로 나중에 다시 시도할 수 있습니다.

먼저 알아둘 동작

tcp_close()는 연결을 정상 종료하도록 요청합니다. 이미 보낸 데이터의 ACK를 전부 기다린 다음에만 호출할 수 있는 함수는 아닙니다. 종료가 완료되면 PCB는 lwIP가 관리하며, 성공 반환 후 애플리케이션이 그 PCB를 다시 참조해서는 안 됩니다.

전체 학습 순서와 다른 문제별 글은 lwIP 학습 로드맵에서 확인할 수 있습니다.

반환값 애플리케이션에서 할 일
ERR_OK 종료 요청이 수락됐습니다. 저장해 둔 PCB 참조를 더 이상 사용하지 않습니다.
ERR_MEM PCB는 해제되지 않았습니다. 상태를 유지하고 ACK 또는 poll callback에서 재시도합니다.
그 밖의 오류 해당 반환 코드와 호출 조건을 확인합니다. 무조건 재시도하지 않습니다.

세부 동작과 반환 조건은 lwIP 2.1.x RAW TCP API 문서를 기준으로 확인하세요. 사용 중인 버전의 API 설명과 포트 설정도 함께 봐야 합니다.

ERR_MEM일 때의 흐름

tcp_close(pcb) returns ERR_MEM
-> keep the PCB and mark close_pending
-> wait for an ACK callback or poll callback
-> retry tcp_close() in a valid lwIP callback context

재시도 사이에는 다른 데이터를 계속 큐에 넣지 말고, 동일한 코어/호출 문맥 규칙을 지킵니다. RAW API callback에서 임의로 RTOS delay를 걸거나 tight loop를 돌려 해결하려 하지 않습니다.

tcp_write()가 먼저 ERR_MEM을 반환하는 문제와 종료 시점의 메모리 오류는 겹칠 수 있지만 같은 문제는 아닙니다. 송신 byte 예산과 queue 길이는 tcp_write()의 ERR_MEM과 송신 큐, 관련 설정은 TCP 버퍼와 메모리 pool에서 확인할 수 있습니다.

확인할 항목

  • tcp_close()가 호출된 시점과 반환 코드
  • 실패 뒤에도 같은 PCB를 보존하고 있는지
  • 재시도가 ACK 또는 poll callback에서 이뤄지는지
  • PCB가 이미 다른 경로에서 닫히거나 무효화되지 않았는지
  • TCP_SND_BUF, TCP_SND_QUEUELEN, MEMP_NUM_TCP_SEG 등 실제 설정과 통계를 함께 봤는지
  • 사용 중인 lwIP 버전과 RAW API 코어 문맥 규칙

tcp_abort()는 정상 종료와 다르게 연결을 즉시 중단합니다. ERR_MEM을 피하려고 바꾸지 말고, 미전송 데이터 손실을 허용하는 경로인지 먼저 구분하세요.

참고 자료

광고