Proceso que retorna 141 en Linux.

Iniciado por 0xDani, 27 Octubre 2012, 20:38 PM

0 Miembros y 1 Visitante están viendo este tema.

0xDani

Bueno pues tengo un programa, lo ejecuto y se corta a la mitad de la ejecucion, y al comprobar el valor de retorno:
echo $?
la salida es 141. ¿Que significa esto?

Saludos.

EDIT: Vale ya lo tengo, se ha enviado una señal SIGPIPE a mi proceso, parece que escribe sobre sockets que no estan conectados. Es decir, se me desconectan los sockets. ¿Puedo tratar de detectar si un socket esta conectado o no y reconectarlo sin que se cierre el programa?¿O de hacer un handler para esta señal?
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

xiruko

Citar¿Puedo tratar de detectar si un socket esta conectado o no y reconectarlo sin que se cierre el programa?¿O de hacer un handler para esta señal?

getpeername()

y para lo otro, aunque ya lo hayas encontrado, por si acaso no lo has hecho asi, tienes todos los errores definidos en el archivo de cabecera syscall.h, que lo tendras en /usr/include o por ahi.

un saludo!

0xDani

Cita de: xiruko en 27 Octubre 2012, 20:54 PM
getpeername()

y para lo otro, aunque ya lo hayas encontrado, por si acaso no lo has hecho asi, tienes todos los errores definidos en el archivo de cabecera syscall.h, que lo tendras en /usr/include o por ahi.

un saludo!

He puesto un getpeername() antes de escribir al socket, y si retorna ENOTCONN (significa que no esta conectado) vuelve a tratar de reconectar hasta que lo consiga, pero sigue igual, se corta y retorna 141.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

xiruko

sin el codigo completo es algo dificil adivinar de donde viene el error... :rolleyes:

0xDani

Cita de: xiruko en 27 Octubre 2012, 21:50 PM
sin el codigo completo es algo dificil adivinar de donde viene el error... :rolleyes:

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <signal.h>

#define MAX_dani 0xF0000

struct params{
  char web[20];
  int port;
  int thread;
  int nrequests;
  int sleeptime;
};

int total_requests;
pthread_mutex_t lock;
int nthreads;

void* t(void *p)
{
  int n = ((struct params*)p)->thread + 1;
  printf("Proceso %i: presente\n", n);
  char request[128];
  char buff[10000] = {'\0'};
  struct hostent *host = gethostbyname(((struct params*)p)->web);
  if(!host)
  {
    printf("Proceso %i: No se ha podido resolver la direccion del servidor\n", n);
    return NULL;
  }
  printf("Proceso %i: host->h_addr: %s\n", n, inet_ntoa(*((struct in_addr *)host->h_addr)));
  struct sockaddr sockbuf;
  int stsize = sizeof(sockbuf);
  struct sockaddr_in sock;
  sock.sin_family = AF_INET;
  sock.sin_port = htons(((struct params*)p)->port);
  sock.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)host->h_addr)));
  printf("Proceso %i: Direccion: %d\n", n, sock.sin_addr.s_addr);

int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockfd==-1)
{
  printf("Proceso %i: No se pudo crear el socket\n", n);
  return NULL;
}
printf("Proceso %i: Socket creado\n", n);
printf("Proceso %i: Conectando...\n", n);
int aux;
connect(sockfd, (struct sockaddr*) &sock, sizeof(struct sockaddr));
printf("Proceso %i: Conectado\n", n);
sprintf(request, "GET / HTTP/1.1\nHost: %s\nUser-Agent: Mozilla/4.0\n\n ", host->h_name);
printf("Proceso %i: Peticion en request\n", n);
for(aux=0; aux<(((struct params*)p)->nrequests); aux++)
{
   switch(getpeername(sockfd, &sockbuf, &stsize))
   {
    case 0: break;
    case ENOTCONN:
     printf("Proceso %i: reconectando socket...", ((struct params*)p)->thread);
     close(sockfd);
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if(connect(sockfd, (struct sockaddr*) &sock, sizeof(struct sockaddr))==-1) continue;
     else break;
   }
   write(sockfd, request, strlen(request));
   printf("Proceso %i: %i peticion/es\n", n, aux+1);
   pthread_mutex_lock(&lock);
   total_requests++;
   sleep((((struct params*)p)->sleeptime)/nthreads);
   pthread_mutex_unlock(&lock);
}
close(sockfd);
pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
pthread_mutex_init(&lock, NULL);
pthread_t *mythreads = (pthread_t*)malloc(atoi(argv[1])*sizeof(pthread_t));
pthread_attr_t a;
struct params *p = (struct params*)malloc(atoi(argv[1])*sizeof(struct params));
int i, ret, j;
nthreads = atoi(argv[1]);
for(j=0; j<nthreads; j++)
{
  strcpy(p[j].web, argv[2]);
  p[j].thread = j;
  p[j].port = atoi(argv[3]);
  p[j].nrequests = atoi(argv[4]);
  p[j].sleeptime = atoi(argv[5]);
}
pthread_attr_init(&a);
pthread_attr_setstacksize(&a, MAX_dani);
for(i=0; i<nthreads; i++)
{
  ret = pthread_create(&mythreads[i], &a, t, &p[i]);
  switch(ret)
  {
   case 0:
    printf("Thread %i creado\n", i+1);
    break;
   case EAGAIN:
    printf("EAGAIN\n");
    _exit(1);
   case EINVAL:
    printf("EINVAL\n");
    _exit(2);
   case EPERM:
    printf("EPERM\n");
    _exit(3);
  }
}
pthread_attr_destroy(&a);
for(j=0; j<nthreads; j++)
pthread_join(mythreads[j], NULL);
pthread_mutex_destroy(&lock);
printf("Retornaron los hilos\n");
printf("Total de peticiones: %i\n", total_requests);
return 0;
}


Es un flooder, o al menos eso intento. Los parametros son: numero_de_threads web puerto(80) numero_de_peticiones_por_thread tiempo_de_espera. Si le pones 2 threads y unos 10 segundos de espera funciona, pero a partir de 3 threads da igual el tiempo que le pongas, llega a hacer 2 o 3 peticiones por thread.

Saludos.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

xiruko

uff a ver nunca he usado esta manera para crear distintos hilos de ejecucion, pero creo que en algo puedo ayudar:

1) en cuanto a tu duda inicial:

switch(getpeername(sockfd, &sockbuf, &stsize))
   {
    case 0: break;
    case ENOTCONN:
     printf("Proceso %i: reconectando socket...", ((struct params*)p)->thread);
     //...


la funcion getpeername() devuelve 0 en caso de que vaya bien, y -1 en caso de error, y es entonces cuando le da un valor a errno que es el que tu tienes que comprobar. el codigo seria algo asi:

aux=getpeername(sockfd, &sockbuf, &stsize);
if (aux<0 && strcmp("ENOTCONN", strerror(errno))==0) {
     //reconectando socket... etc


2) veo muchas reservas de memoria pero ningun free(). aunque lo normal es que los so modernos se encarguen de liberarla al finalizar el programa, nunca esta de mas ponerlo por si las moscas y para evitar posibles quebraderos de cabeza. te dejo un enlace corto que habla sobre ello:

http://cboard.cprogramming.com/cplusplus-programming/76877-general-malloc-question.html

3) cuando declaras el array de structs:

struct params *p = (struct params*)malloc(atoi(argv[1])*sizeof(struct params));

lo haces como un puntero, pero luego accedes a ellos de esta manera:

p[j].thread = j;
p[j].port = atoi(argv[3]);


no deberias acceder a los campos del struct asi:

*(p[j]).thread=j;

o lo que es lo mismo, asi:

p[j]->thread=j;

en lugar de como tu lo haces? tenia entendido que hacerlo como tu lo haces era solo para un struct estatico. quizas he dicho una burrada, pero me refiero a que pensaba que era para una variable que la declaras asi (lo de estatico no se si esta bien dicho):

struct params p;

y no como un puntero. te funciona bien? si es asi ya lo se para la proxima vez. aunque entonces no se que utilidad tiene el operador '->'.

4) es un codigo que aunque no sea demasiado largo es bastante denso. tu eres quien lo ha codeado y quizas no tengas problemas, pero para quien quiera leerlo e intentar entenderlo cuesta bastante. unos cuantos espaciados y algun que otro comentario ayudarian bastante, y tambien te ayudarian a ti en caso de que dentro de unos meses quieras volver a mirarte el codigo.


5) si no te es mucha molestia podrias colgar el codigo cuando lo acabes ya que a mas de uno le vendra bien para aprender (yo incluido).

un saludo!

pd. estas haciendo este flooder para aquel proyecto en el que os juntasteis unos cuantos de este foro?

0xDani

#6
 1) Epic fail. Gracias por hacermelo ver!
2) Me di cuenta esta noche, ya esta corregido, pero gracias de todas formas.
3) La funcion malloc devuelve un puntero al primer elemento del array. Es decir, p es un puntero a una estructura, equivale a &p[0], luego p[0] es la estructura.
4) Si, debe ser una buena costumbre documentar el codigo...  :silbar:
5) Claro, estare encantado de colgarlo.

Bueno voy a ver si me funciona el codigo corrigiendo el fallo y lo cuelgo.

Saludos.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM