c - Problem with select when closing socket -
i'm doing multiclient server accepts connection, forks, , gives connection child can handle it. it's multiclient server, has multiple children.
the main process in infinite while
makes select
find out if there new incoming connection or if child trying communicate.
the problem arises when close client (which connected son of main server): randomly happens client connection closed, , select gets unblocked because supposedly internal socket (which handles incoming connection between children , main server) modified, far concerned not true. happened client closed connection , child died.
can give me clue of it's going on here? i'm quite lost.
this code of infinite loop in main server:
while (1) { /*inicializo variables para el select*/ sflag = 0; fd_zero(&readfds); fd_set(sockfd, &readfds); fd_set(sockifd,&readfds); max = (sockfd > sockifd) ? sockfd : sockifd; for(aux = isockets; aux != null; aux = aux -> next){ fd_set(aux -> sd, &readfds); max = (max > aux -> sd) ? max : aux -> sd; } printf("pre-select\n"); select(max + 1, &readfds, null, null, null); /*checkeo si salio por actividad en un socket interno*/ (aux = isockets; aux != null; aux = aux -> next){ if (fd_isset(aux -> sd, &readfds)){ printf("comunicacion con el socket: %d\n", aux -> sd); sflag = 1; actsocket = aux -> sd; break; } } if (sflag == 1){//mensaje de un hijo n = recv(actsocket, buffer, sizeof(buffer), 0); if (n == 0) { printf("conexion cerrada con el socket interno: %d\n", actsocket); close(actsocket); isockets = free_sock(isockets, actsocket); printf("isockets: %p\n", isockets); } else if(n < 0) error ("error en comunicacion interna"); else printf("mensaje del boludon: %s\n", buffer); } else if (fd_isset(sockifd, &readfds)){// un hijo inicia conexion interna printf("antes de accpet interno\n"); newisockfd = accept(sockifd, (struct sockaddr *) &ucli_addr, &uclilen); printf("nueva conexion interna, socketfd: %d\n", newisockfd); isockets = add_socket(isockets,newisockfd, 0); recorre(isockets); if (newisockfd < 0) error ("error en accept unix, padre"); } else if (fd_isset (sockfd, &readfds)){/*conexion entrante*/ printf("conexion entrante\n"); newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("error on accept"); pid = fork(); if (pid < 0) error("error on fork"); if (pid == 0){//hijo close(sockfd); dostuff(newsockfd, path, tm,fd[0]); exit(0); } else { //padre printf("conexion aceptada, pid hijo %d\n", pid); close(newsockfd); } } }
so, randomly, when close connection, select unblock if "sockifd" modified, wasn't. don't know why doing that.
one thing wrong in code you're not checking return value of select
.
if select
interrupted signal (returns -1
errno = eintr
, example sigchld
if 1 of children died), contents of &readfds
undefined, , must not read. (see example linux man page select
.)
so check return value if select
, , loop right without going through &readfds
processing if there's temporary error eintr
.
Comments
Post a Comment