문제 개요
- 패킷 매니저에서 연속적으로 패킷을 보내는 과정에서
sendQueue 처리 시 구조분해 할당 오류가 발생.
원인 분석
- 큐 접근 문제: 빈 큐에서 데이터를
shift() 하려다 에러 발생.
- 동시성 문제: 이미
processSendPacket이 실행 중인데 enQueueSend가 processSendPacket을 호출해 뮤텍스 대기 상태에 빠짐.
enQueueSend
async enQueueSend(socket, packet) {
await this.sendLock.runExclusive(() => {
this.sendQueue.push({ socket, packet });
this.processSendPacket();
});
}
deQueueSend
async deQueueSend() {
return await this.sendLock.runExclusive(() => {
return this.sendQueue.shift();
});
}
processSendPacket
async processSendPacket() {
if (!this.sendQueue.length) return;
try {
while (this.sendQueue.length) {
const { socket, packet } = await this.deQueueSend();
if (!socket || !packet) throw new Error('패킷 보내기 오류');
await socket.write(packet);
}
} catch (err) {
handleErr(null, err);
}
}
- 플래그 추가:
processSendPacket 실행 중인 상태를 확인하는 sendProcessing 플래그를 추가.
- 이미 실행 중이면 조기 종료.
결론
processSendPacket
async processSendPacket() {
if (!this.sendQueue.length || this.sendProcessing) return;
this.sendProcessing = true;
try {
while (this.sendQueue.length) {
const { socket, packet } = await this.deQueueSend();
if (!socket || !packet) throw new Error('패킷 보내기 오류');
await socket.write(packet);
}
} catch (err) {
handleErr(null, err);
} finally {
this.sendProcessing = false;
}
}
- 플래그를 통해 중복 실행 방지로 안정적으로 패킷을 처리하도록 수정.
해결