PRS_UNIRIO
(usa Ubuntu)
Enviado em 28/09/2012 - 20:00h
Vamos ao problema passo-a-passo:
1. Rodo um processo no linux em background.
2. Esse processo abre uma porta, nesse momento um bind é enviado ao sistema operacional.
3. Mato o processo através do killall.
4. O killall não envia ao sistema operacional uma instrução para que ele desfaça o bind, liberando com isso a porta.
5. Rodo o processo novamente e recebo a mensagem de erro "Essa porta já está em uso".
De acordo com o que já li o linux suporta cerca de 65.000 conexões simultâneas nas portas e o TIME_WAIT delas é relativamente curto.
Não cheguei nem perto de 65 conexões e essa p*#$@ de TIME_WAIT fica agarrado durante meses!
A pergunta é: O processo está morto. Como matar o bind no linux?
Desde já agradeço a todos.
Detalhes de como o problema acontece:
Varias execuções do Azureus/Vuze em background no Linux ( com "&" )
seguidas de paradas bruscas realizadas por "killall -9 java" resultaram
no problema da porta.
Conteúdo do arquivo em Shell Script para rodar o Azureus/Vuze.
===============================
#!/bin/bash
java -jar Azureus2.jar --ui=console $1
===============================
Como é executado e interrompido:
===============================
[rnp_letra_unirio@planetlab2]$ ./Vuze.sh &
[rnp_letra_unirio@planetlab2]$ killall -9 java
===============================
Vejam o resultado dos comandos lsof, netstat e ps:
===============================
mac@micro:~$ ssh rnp_letra_unirio@planetlab-02.bu.edu
Last login: Fri Sep 28 21:51:12 2012 from fwa.uniriotec.br
[rnp_letra_unirio@planetlab-02 ~]$ export JAVA_HOME="/usr/lib/jvm/jre1.6.0_34"; export PATH="$PATH:$JAVA_HOME/bin"
[rnp_letra_unirio@planetlab-02 ~]$ cd vuze
[rnp_letra_unirio@planetlab-02 vuze]$ java -jar Azureus2.jar --ui=console
file:/home/rnp_letra_unirio/vuze/Azureus2.jar ; file:/home/rnp_letra_unirio/vuze/
StartServer ERROR: unable to bind to 127.0.0.1:6880 for passed torrent info
StartSocket: passing startup args to already-running process.
[rnp_letra_unirio@planetlab-02 vuze]$ cd ..
[rnp_letra_unirio@planetlab-02 ~]$ java -jar Socket.jar
java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(Unknown Source)
at java.net.ServerSocket.bind(Unknown Source)
at Main.main(Main.java:18)
[rnp_letra_unirio@planetlab-02 ~]$ netstat -tulnap
(No info could be read for "-p": geteuid()=774 but you should be root.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
[rnp_letra_unirio@planetlab-02 ~]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 7981 0.0 0.0 2656 1076 ? Ss 22:16 0:00 /bin/su - rnp_l
774 8016 0.0 0.0 2632 1408 ? S 22:16 0:00 -bash
774 12500 0.0 0.0 2448 820 ? R+ 22:18 0:00 ps aux
[rnp_letra_unirio@planetlab-02 ~]$ /usr/sbin/lsof -i :6880
[rnp_letra_unirio@planetlab-02 ~]$
===============================
Já tentei excluir a maquina no slice do PlanetLab, mas não funcionou. Os arquivos são mantidos e o problema também.
Apagar tudo e reinstalar também não resolveu.
Reboot com os comandos abaixo também não funcionou:
===============================
mac@micro:~$ ssh rnp_letra_unirio@planetlab2.pop-rs.rnp.br
[rnp_letra_unirio@planetlab2]$ cd /sbin
[rnp_letra_unirio@planetlab2 sbin]$ sudo mkfifo /dev/initctl
[rnp_letra_unirio@planetlab2 sbin]$ sudo ./reboot -f
===============================
O programa do Azureus/Vuze é bem complexo, por isso fiz o programa abaixo para facilitar o entendimento (o Socket.jar executado acima):
===============================
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class Main {
private static ServerSocket socket;
public static void main(String[] args) {
try {
socket = new ServerSocket(6880, 50, InetAddress.getByName("127.0.0.1"));
System.out.println("Porta OK");
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
===============================
A modificação do código para permitir reutilização de porta não resolve o problema.
===============================
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class Main {
private static ServerSocket socket;
public static void main(String[] args) {
try {
ServerSocket socket = new ServerSocket();
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(6880),50);
System.out.println("Porta OK");
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}