Antecedentes
O soquete entra no estado CLOSE_WAIT quando a extremidade remota termina a conexão enviando um pacote com o sinalizador FIN definido. Em seguida, ele espera nesse estado pelo aplicativo local para close()
do soquete e, em seguida, envia seu próprio FIN para o cliente e transiciona o soquete para o estado LAST_ACK. Veja também o diagrama de transição do estado TCP e RFC 793 .
Note também que CLOSE_WAIT não está relacionado com o infame TIME_WAIT, pois o primeiro ocorre no ramo próximo passivo (o final remoto fecha primeiro), enquanto o segundo no ramo próximo ativo (fim local fecha primeiro).
Descrição do problema
Normalmente, as conexões fazem a transição de CLOSE_WAIT para LAST_ASK com bastante rapidez. Se o endereço remoto e a porta continuarem mudando rapidamente, um número razoável de conexões no estado CLOSE_WAIT pode ser simplesmente a consequência de um número muito grande de conexões abertas, usadas e fechadas. O desempenho do sistema deve ser examinado, mas por si só não constitui um problema.
Se o endereço remoto e a porta mudarem lentamente, isso indica que os processos de aplicativos precisam aguardar a CPU, caso em que altas médias de carga confirmarão isso.
Se, por outro lado, o endereço e a porta remotos permanecerem constantes e o número de conexões no estado CLOSE_WAIT continuar crescendo, é muito provável que exista um problema com o aplicativo. Este é um caso especial do erro de vazamento de recursos: o aplicativo vaza sockets abertos em vez de fechar oportunamente eles. Isso consome a memória do kernel e eventualmente fará com que o aplicativo falhe quando atingir o número máximo de descritores de arquivos abertos.
Note, entretanto, que o ritmo do vazamento pode ser lento. É comum que erros como esse resultem de uma falha ao manipular uma exceção no meio de uma solicitação, interrompendo o fluxo de execução em um thread de trabalho, o que pode impedir a limpeza subsequente (incluindo o fechamento de soquete). A exceção incorreta pode ocorrer raramente.
Solução temporária
A solução temporária para o problema é aumentar os limites dos descritores de arquivos abertos e reiniciar periodicamente o aplicativo quando (preferencialmente antes) o problema começar a afetar o desempenho. Observe que isso pode afetar inadvertidamente as conexões abertas no momento. A existência de servidores redundantes e o balanceamento de carga podem ajudar a ocultar o problema dos usuários.
Solução permanente
Solução permanente para o problema é implantar a versão do aplicativo sem o bug. O grau em que a solução temporária prejudica os usuários e os negócios, a prontidão da liberação corrigida e o estado da última liberação de trabalho ajudam a decidir se a reversão para a última versão de trabalho do aplicativo ou a espera pela correção.