Passa al contenuto principale

In questo post vorrei discutere di un errore di codifica comune che può portare ad un modulo che esaurisce o almeno esaurisce seriamente il numero disponibile di cloni di dispositivi stcp da utilizzare per la creazione di prese TCP.

Ogni chiamata alla funzione socket comporta la creazione di un nuovo clone del dispositivo stcp da parte di STCP. Il numero massimo di cloni che possono essere creati è controllato dal campo clone_limit nella voce devices.tin.

/ =nome stcp.m17
     =nome_modulo m17
     =flussi di tipo_dispositivo
     =accesso_elenco_nome_lista stcp_accesso
     =streams_driver stcp
     =clone_limit 5120
     =commento Fornisce API TCP

Si può vedere quanti cloni sono attualmente in uso scaricando la struttura del dispositivo in analyz_system e guardando il valore di clone_count. Se clone_count è uguale a clone_limit, le chiamate alla funzione socket restituiranno un e$clone_limit_exceeded: Errore "Il limite del clone per il dispositivo è stato superato".

come: clone match; dump_dvt - nome stcp.m17
clone_limit: 5120
clone_count:       42
clonato_da: -27271
limite_clone_remoto: 0

In generale, la chiamata della presa che crea il dispositivo clone è seguita da un collegatevi a chiamare o legare e ascoltare chiamate. A quel punto si può vedere una voce corrispondente quando si esegue il "comando netstat".

netstat -numerico - tutte_prese_tutte_tutte_le_prese
Connessioni attive (compresi i server)
Proto Recv-Q Send-Q Indirizzo locale Indirizzo estero (stato)
tcp 0 0 172.16.124.217:23 192.168.109.22:50038 ISTITUITO
tcp 0 0 172.16.124.217:22 172.16.124.24:54987 ISTITUITO
tcp 0 0 10.20.1.1:37 10.20.1.26:1528 TIME_WAIT
tcp 0 0 10.20.1.1:37 10.20.1.27:1579 TIME_WAIT
tcp 0 0 172.16.124.217:61780 192.168.109.22:23 ISTITUITO
tcp 0 0 172.16.124.217:22 172.16.124.50:17421 ISTITUITO
tcp 0 0 172.16.124.217:22 172.16.124.50:17658 ISTITUITO
tcp 0 0 0 *:23 *:* ASCOLTA
tcp 0 0 0 *:6666 *:* ASCOLTO
tcp 0 0 0 *:21 *:* ASCOLTA
tcp 0 0 0 *:3000 *:* ASCOLTA
tcp 0 0 0 *:7 *:* ASCOLTA
tcp 0 0 0 *:9 *:*:* ASCOLTA
tcp 0 0 0 *:13 *:* ASCOLTA
tcp 0 0 0 *:19 *:* ASCOLTA
tcp 0 0 0 *:37 *:* ASCOLTA
tcp 0 0 0 *:901 *:*:* ASCOLTA
tcp 0 0 0 *:1414 *:* ASCOLTA
tcp 0 0 0 *:81 *:* ASCOLTA
tcp 0 0 10.20.1.1:37 10.20.1.9:3633 TIME_WAIT
tcp 0 50 10.10.1.1:52653 10.10.1.200:3001 STABILITATO
tcp 0 0 0 10.10.1.1:52624 10.10.1.200:3001 FIN_WAIT_1
tcp 0 0 10.20.1.1:61704 10.20.1.3:48879 ISTITUITO
tcp 0 0 0 *:3001 *:* ASCOLTA
tcp 0 0 0 *:3002 *:* ASCOLTA
tcp 0 0 0 *:3003 *:* ASCOLTA
tcp 0 0 0 *:4000 *:* ASCOLTA
tcp 0 0 172.16.124.217:4000 172.16.124.78:1024 ISTITUITO
tcp 0 0 172.16.124.217:4000 172.16.124.227:1025 ISTITUITO
tcp 0 0 0 *:4001 *:* Ascolta
tcp 0 0 0 *:4002 *:* ASCOLTA
tcp 0 0 0 *:4003 *:* ASCOLTA
tcp 0 0 0 *:4004 *:* ASCOLTA
tcp 0 0 0 *:22 *:* ASCOLTA
tcp 0 0 0 *:4005 *:* ASCOLTA
tcp 0 0 0 *:4006 *:* ASCOLTA
tcp 0 0 172.16.124.217:4006 172.16.124.203:49231 ISTITUITO
tcp 0 0 0 *:4007 *:* ASCOLTA
tcp 0 0 0 *:4008 *:* ASCOLTA
tcp 0 0 0 *:4009 *:* ASCOLTA
tcp 0 0 172.16.124.217:4008 172.16.124.203:49262 ISTITUITO
tcp 0 0 0 *:4010 *:* Ascolta
tcp 0 0 0 *:4011 *:* ASCOLTO
tcp 0 0 0 *:4012 *:* ASCOLTO
tcp 0 0 0 *:4013 *:* ASCOLTO
tcp 0 0 0 *:4014 *:* ASCOLTO
tcp 0 0 0 *:4015 *:* ASCOLTO
tcp 0 0 0 *:80 *:*:* ASCOLTA
tcp 0 0 0 *:9182 *:* ASCOLTO
tcp 0 0 0 *:445 *:* ASCOLTO
tcp 0 0 0 *:139 *:* ASCOLTA
tcp 0 0 10.20.1.1:53495 10.20.1.9:48879 ISTITUITO
tcp 0 0 10.20.1.1:61703 10.20.1.3:48879 ISTITUITO
tcp 0 0 10.20.1.1:61707 10.20.1.3:48879 ISTITUITO
tcp 0 0 10.20.1.1:61705 10.20.1.9:48879 ISTITUITO
tcp 0 0 10.20.1.1:61709 10.20.1.9:48879 ISTITUITO
tcp 0 0 10.20.1.1:61710 10.20.1.9:48879 ISTITUITO
tcp 0 0 172.16.124.217:61789 172.16.124.203:4000 ISTITUITO
tcp 0 400 172.16.124.217:22 172.16.124.50:17674 ISTITUITO

Se si conta il numero di righe si vedranno più di 42, questo perché non tutte le voci mostrate da netstat utilizzano un clone di dispositivo stcp. Per esempio, le connessioni OSL e le connessioni X25_cpc utilizzate con il NIO. Date un'occhiata a socket_count.cm per maggiori dettagli.

Se una chiamata alla presa viene effettuata senza un collegamento o un bind o il bind fallisce è possibile creare il problema opposto, il valore di clone_count è maggiore del numero di voci mostrato da netstat.

come: clone match; dump_dvt - nome stcp.m17
clone_limit: 5120
clone_count:       4131
clonato_da: -23179
limite_clone_remoto: 0
come:

Non includo di nuovo l'output netstat, ma credetemi, non è cambiato rispetto all'esempio precedente.

Questa situazione, un ulteriore (4131 - 42) e apparentemente non contabilizzata, cloni di dispositivi STCP è stata creata dal seguente frammento di codice. Il codice chiama la funzione socket seguita dalla funzione bind. Se il bind fallisce, il codice si chiude in loop. Molte applicazioni aggiungerebbero un timer per attendere 1, 60, o 300 secondi e riprovare, che ritarda solo l'inevitabile, supponendo ovviamente che la condizione che causa l'errore non vada via.

tryAgain = 1;
while (tryAgain)
  {
  if ((socks0 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
     {
     if (debugFlag)
        perror ("badService: can't create listening socket");
     }
  else {
/* build a sockaddr structure holding the address we will bind to.
   The IP address is INADDR_ANY meaning we will listen on all active
   IP addresses */

     bzero ( (char *) &serv_addr, sizeof (serv_addr));
     serv_addr.sin_family        = AF_INET;
     serv_addr.sin_addr.s_addr   = htonl (INADDR_ANY);
     serv_addr.sin_port          = htons (portNumber);

/* now bind to the address and port */
     if (bind (socks0, (struct sockaddr *) &serv_addr,
                                      sizeof (serv_addr)) < 0)
        {
        if (debugFlag)
           perror ("badService: can't bind address, trying again");
        }
     else
        tryAgain = 0;
     }
   }

L'errore più comune è che un altro processo è già legato alla porta richiesta. Indipendentemente dal motivo dell'errore, la soluzione è quella di chiudere il socket dopo aver segnalato l'errore di binding.

tryAgain = 1;
while (tryAgain)
  {
  if ((socks0 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
     {
     if (debugFlag)
        perror ("goodService: can't create listening socket");
     }
  else {
/* build a sockaddr structure holding the address we will bind to.
   The IP address is INADDR_ANY meaning we will listen on all active
   IP addresses */

     bzero ( (char *) &serv_addr, sizeof (serv_addr));
     serv_addr.sin_family        = AF_INET;
     serv_addr.sin_addr.s_addr   = htonl (INADDR_ANY);
     serv_addr.sin_port          = htons (portNumber);

/* now bind to the address and port */
     if (bind (socks0, (struct sockaddr *) &serv_addr,
                                      sizeof (serv_addr)) < 0)
        {
        if (debugFlag)
           perror ("goodService: can't bind address, trying again");
        if (close (socks0) < 0)
           if (debugFlag)
              perror ("goodService: can't close old socket");
        }
     else
        tryAgain = 0;
     }
   }

 

Questo post parlava di raggiungere il clone_limit a causa di un errore di codifica, ma cosa succede se non c'è nessun errore, cosa succede se l'ambiente applicativo sta realmente usando tutti quei dispositivi di clonazione. Bene allora, supponendo di non aver raggiunto il limite di sistema di 16.000 è possibile aumentare il limite. È necessario aggiornare il campo clone_limit del dispositivo stcp nel file devices.tin e ricreare il device.table. Se siete su una release 17.1 o successiva potete usare il comando update_device_info per aumentare il limite per l'avvio corrente e fare affidamento sul device.table aggiornato devices.table per occuparvi del prossimo avvio. Nelle release precedenti alla 17.1 l'unica opzione reale è il riavvio. Si dovrebbe impostare il limite ad un valore che corrisponda alle proprie esigenze attuali più la crescita prevista; non si dovrebbe semplicemente aumentare il limite a 16.000. Anche se non si dispone di un bug dell'applicazione che sta consumando dispositivi di clonazione ora non c'è garanzia che non ne avrete uno in futuro. Un'applicazione che sta consumando tutti i dispositivi di clonazione disponibili consumerà anche una grande quantità di memoria di flussi e l'esaurimento della memoria dei flussi influenzerà negativamente le connessioni TCP esistenti.

© 2024 Stratus Technologies.