I have a weird issue with a server written in C.
I have a function that is treating each client that connects to my server, so this function calls a fork() for each connection that the server receives.
The issue is that I have other forks inside that client-fork
that are supposed to write an exec()
's output inside a file that I created .I dup2()
that file's descriptor with stdout so that the output can be read from the file inside the parent right after the second child process (the one with exec()
call) dies.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#define PORT 2021
extern int errno;
void signal_handler( int sig )
{
printf("[Server]Cought signal SIGCHLD\n");
while( waitpid(-1, NULL, WNOHANG) > 0 )
{
}
}
int TreatClient(int clientSocket, int nr)
{
int pid1,wait1;
if ((pid1 = fork()) == -1)
{
printf("eroare pid");
exit(1);
}
if(pid1 == 0) // treat client
{
printf("START TREAT CLIENT!\n");
nr++;
int saved_stdout;
char filename[3];
snprintf(filename, 3,"%d",nr);
int pid2,wait2;
saved_stdout = dup(1);
if ((pid2 = fork()) == -1)
{
printf("eroare pid");
exit(1);
}
if(pid2 == 0)
{
printf("START DUP child!\n");
int fd = open("fisier",O_CREAT|O_RDWR,00700);
dup2(fd,1);
printf("child 2 !\n");
close(fd);
return 1;
}
else
{
int fil;
char chara;
wait(&wait2);
dup2(saved_stdout,1);
close(saved_stdout);
fil = open("fisier",O_RDONLY,00700);
while(read(fil,&chara,1)!=-1 && chara != '\n') printf("%c",chara);
printf("\nEND PARENT dup !\n");
}
printf("TREAT CLIENT END!\n");
return 1;
}
else
{
wait(&wait1);
printf("END MAIN!\n");
}
return 1;
} /* while */
return 0;
return 1;
}
int main()
{
struct sockaddr_in server;
struct sockaddr_in from;
char msg[100];
char rply[100]=" ";
int sd;
int on, status, nr = 0;
if( signal(SIGCHLD, signal_handler) < 0 )
{
printf("[Server]Signal Error : %d !\n", errno);
exit(-5);
}
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("[server]Socket Error !\n");
return errno;
}
on = 1;
status = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on));
if ( status == -1 )
{
printf("[server]Setsockopt() Error : %d !\n", errno);
exit(-1);
}
bzero (&server, sizeof (server));
bzero (&from, sizeof (from));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl (INADDR_ANY);
server.sin_port = htons (PORT);
if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
{
printf("[server]Bind Error : %d!\n", errno);
exit(-2);
}
if (listen (sd, 5) == -1)
{
printf ("[server]Listen Error : %d!\n", errno);
exit(-3);
}
///////////////////////////////////////////////////////////////////////////////////////////
/* client-iteration*/
while (1)
{
int client;
int length = sizeof (from);
printf ("[server]Waiting at port %d...\n",PORT);
fflush (stdout);
client = accept (sd, (struct sockaddr *) &from, &length);
nr++;
if (client < 0)
{
printf ("[server]Accept Error : %d!\n", errno);
continue;
}
printf("[server]Client number %d connected\n", nr);
TreatClient(client, nr);
return 1;
}
The desired output is simmilar to this :
[server]Waiting at port 2021...
[server]Client number 1 connected
START TREAT CLIENT!
START DUP child!
[Server]Cought signal SIGCHLD
child 2 !
END PARENT dup !
TREAT CLIENT END!
[Server]Cought signal SIGCHLD
END MAIN!
The code does not produce the desired output. It becomes stuck after DUP2 and the rest of the output is redirected towards the file. But if i replace the TreatClient(client, nr);
line with the function block the code works as it should. Why is this happening ? Another weird issue is that the message [server]Waiting at port 2021...
is also printed in the file and not on the screen .