logicTRANCE
asked on
Socket programming; server side; signal 11(segmentation fault) ??!!
Hi!
I'm implementing a simple chat server.
It starts up fine, binding et.al. is fine...
then when i connect to it using telnet 127.0.0.1 19471
(this is the port number i'm listening on #define CONTROL_PORT 19471),
the server crashes.
the messege at server terminal is:
Program has been terminated receiving signal 11 (Segmentation fault)
Press the Enter key to close this terminal ...
on the client(telnet) terminal, the msg is:
telnet 127.0.0.1 19471
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.
What is going wrong?
Here's a snippet of my server code:
int main()
{
int DataTempSock, CtrlTempSock; //these will temporarily hold the sockets numbers for every client that connects
int ListenerSock = socket(AF_INET,SOCK_STREAM ,0);
if(ListenerSock == -1)
{
perror("socket()");
return 0;
}
int yes = 1;
if(setsockopt(ListenerSock ,SOL_SOCKE T,SO_REUSE ADDR,&yes, sizeof(int )) == -1)
{
perror("setsockopt()");
close(ListenerSock);
return 0;
}
struct sockaddr_in LisSockAddr;
bzero(&LisSockAddr,sizeof( struct sockaddr_in));
LisSockAddr.sin_family = AF_INET;
LisSockAddr.sin_port = htons(CONTROL_PORT);
LisSockAddr.sin_addr.s_add r = inet_addr("127.0.0.1");
if(bind(ListenerSock, (struct sockaddr*) &LisSockAddr, sizeof(struct sockaddr_in)))
{
perror("bind()");
close(ListenerSock);
return 0;
}
if(listen(ListenerSock,2))
{
perror("listen()");
close(ListenerSock);
return 0;
}
OnlineUsersList OUL; //this is the one and only OnlineUsersList object
fd_set MasterFDSet,TempFDSet; //fdsets to hold active socket lists
//after every 5 seconds, the server will check if all connected clients are still online or not
//this is to make the server resilient against remote system crashes etc. which diconnects remote client
//before proper logout!
struct timeval ServerCheckTimer;
ServerCheckTimer.tv_sec = 5;
ServerCheckTimer.tv_usec = 0;
int MaxSock = ListenerSock; //maintain maximum socket number for select() call
char ReadBuffer[1501]; //all messeages received will be temporarily stored here
int readlen = 0; //number of bytes received
FD_ZERO(&MasterFDSet);
FD_ZERO(&TempFDSet);
FD_SET(ListenerSock,&Maste rFDSet);
int RetValofSelectFn=0;
while(1)
{
TempFDSet = MasterFDSet;
if((RetValofSelectFn = select(MaxSock+1,&TempFDSe t,NULL,NUL L,&ServerC heckTimer) ) == -1)
{
perror("select()");
close(ListenerSock);
return 0;
}
else if(RetValofSelectFn) //something's incoming, let's find out what
{
for(int i=0; i<=MaxSock; i++)
{
if(FD_ISSET(i,&TempFDSet))
{
if(i == ListenerSock) //someone new wants to connect
{
ConnectNewClient(OUL, ListenerSock, &MaxSock, &MasterFDSet);
/* int sockaddrlen = sizeof(TempSockAddr);
if((TempSock = accept(ListenerSock,(struc t sockaddr*)&TempSockAddr,(s ocklen_t*) &sockaddrl en)) == -1)
{
perror("accept()");
}
else
{
if(TempSock > MaxSock) MaxSock=TempSock;
FD_SET(TempSock,&MasterFDS et);
printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd dr.sin_add r),TempSoc k);
}*/
}
else
{
bzero(&ReadBuffer,sizeof(R eadBuffer) );
if((readlen = recv(i,ReadBuffer,sizeof(R eadBuffer) ,0)) <= 0)
{
if(readlen == 0)
{
printf("\nClient at socket %d closed connection!\n",i);
}
else
{
perror("recv()");
printf("\nError reading socket %d, closing that connection\n",i);
}
FD_CLR(i,&MasterFDSet);
close(i);
}
else //recv() successful
{
for(int j=0; j<=MaxSock; j++)
{
if(FD_ISSET(j,&MasterFDSet ))
{
if(j != i && j != ListenerSock)
{
if(safesend(j,ReadBuffer,r eadlen,0) == -1)
{
perror("send()");
printf("Couldn't send messege to client at socket %d, closing that socket\n",j);
FD_CLR(j,&MasterFDSet);
close(j);
}
}
}
}
}
}
}
}
}
else //this will be the case when timeout occurs on call to select
//now check if all clients in OUL are still online
{
}
}
return 0;
}
int safesend(int SendSock,char *SendBuffer,int SendBytesCount,int SendFlag)
{
int BytesSent = send(SendSock,SendBuffer,S endBytesCo unt,SendFl ag);
if(BytesSent == -1)
{
perror("send()");
return -1;
}
else if(BytesSent < SendBytesCount)
{
int RemainingBytes = SendBytesCount - BytesSent;
int temp = 0;
while(RemainingBytes)
{
temp = send(SendSock,SendBuffer+B ytesSent,R emainingBy tes,SendFl ag);
if(temp == -1)
{
perror("send()");
return -1;
}
BytesSent += temp;
RemainingBytes -= temp;
}
}
return BytesSent;
}
//whenever a client tries to connect, this function will be called
//this function
int ConnectNewClient(OnlineUse rsList OUL, int ListenerSock, int *MaxSock, fd_set *MasterFDSet)
{
//a sockaddr_in structure where information about a client requesting to get online
struct sockaddr_in TempSockAddr;
bzero(&TempSockAddr,sizeof (struct sockaddr_in));
int sockaddrlen = sizeof(TempSockAddr);
int TempSock; //socket number allocated to the new client will be temporarily stored here
if((TempSock = accept(ListenerSock,(struc t sockaddr*)&TempSockAddr,(s ocklen_t*) &sockaddrl en)) == -1)
{
perror("accept()");
return (-1);
}
else
{
if(TempSock > *MaxSock) *MaxSock=TempSock;
FD_SET(TempSock,MasterFDSe t);
printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd dr.sin_add r),TempSoc k);
printf("\nMaxSock = %d",*MaxSock);
return (TempSock);
}
}
As you can see...in function ConnectNewClient(),
the line printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd dr.sin_add r),TempSoc k);
is getting executed..but not the printf() following it?! why so?
Please help!
Regards,
logicTRANCE
I'm implementing a simple chat server.
It starts up fine, binding et.al. is fine...
then when i connect to it using telnet 127.0.0.1 19471
(this is the port number i'm listening on #define CONTROL_PORT 19471),
the server crashes.
the messege at server terminal is:
Program has been terminated receiving signal 11 (Segmentation fault)
Press the Enter key to close this terminal ...
on the client(telnet) terminal, the msg is:
telnet 127.0.0.1 19471
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.
What is going wrong?
Here's a snippet of my server code:
int main()
{
int DataTempSock, CtrlTempSock; //these will temporarily hold the sockets numbers for every client that connects
int ListenerSock = socket(AF_INET,SOCK_STREAM
if(ListenerSock == -1)
{
perror("socket()");
return 0;
}
int yes = 1;
if(setsockopt(ListenerSock
{
perror("setsockopt()");
close(ListenerSock);
return 0;
}
struct sockaddr_in LisSockAddr;
bzero(&LisSockAddr,sizeof(
LisSockAddr.sin_family = AF_INET;
LisSockAddr.sin_port = htons(CONTROL_PORT);
LisSockAddr.sin_addr.s_add
if(bind(ListenerSock, (struct sockaddr*) &LisSockAddr, sizeof(struct sockaddr_in)))
{
perror("bind()");
close(ListenerSock);
return 0;
}
if(listen(ListenerSock,2))
{
perror("listen()");
close(ListenerSock);
return 0;
}
OnlineUsersList OUL; //this is the one and only OnlineUsersList object
fd_set MasterFDSet,TempFDSet; //fdsets to hold active socket lists
//after every 5 seconds, the server will check if all connected clients are still online or not
//this is to make the server resilient against remote system crashes etc. which diconnects remote client
//before proper logout!
struct timeval ServerCheckTimer;
ServerCheckTimer.tv_sec = 5;
ServerCheckTimer.tv_usec = 0;
int MaxSock = ListenerSock; //maintain maximum socket number for select() call
char ReadBuffer[1501]; //all messeages received will be temporarily stored here
int readlen = 0; //number of bytes received
FD_ZERO(&MasterFDSet);
FD_ZERO(&TempFDSet);
FD_SET(ListenerSock,&Maste
int RetValofSelectFn=0;
while(1)
{
TempFDSet = MasterFDSet;
if((RetValofSelectFn = select(MaxSock+1,&TempFDSe
{
perror("select()");
close(ListenerSock);
return 0;
}
else if(RetValofSelectFn) //something's incoming, let's find out what
{
for(int i=0; i<=MaxSock; i++)
{
if(FD_ISSET(i,&TempFDSet))
{
if(i == ListenerSock) //someone new wants to connect
{
ConnectNewClient(OUL, ListenerSock, &MaxSock, &MasterFDSet);
/* int sockaddrlen = sizeof(TempSockAddr);
if((TempSock = accept(ListenerSock,(struc
{
perror("accept()");
}
else
{
if(TempSock > MaxSock) MaxSock=TempSock;
FD_SET(TempSock,&MasterFDS
printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd
}*/
}
else
{
bzero(&ReadBuffer,sizeof(R
if((readlen = recv(i,ReadBuffer,sizeof(R
{
if(readlen == 0)
{
printf("\nClient at socket %d closed connection!\n",i);
}
else
{
perror("recv()");
printf("\nError reading socket %d, closing that connection\n",i);
}
FD_CLR(i,&MasterFDSet);
close(i);
}
else //recv() successful
{
for(int j=0; j<=MaxSock; j++)
{
if(FD_ISSET(j,&MasterFDSet
{
if(j != i && j != ListenerSock)
{
if(safesend(j,ReadBuffer,r
{
perror("send()");
printf("Couldn't send messege to client at socket %d, closing that socket\n",j);
FD_CLR(j,&MasterFDSet);
close(j);
}
}
}
}
}
}
}
}
}
else //this will be the case when timeout occurs on call to select
//now check if all clients in OUL are still online
{
}
}
return 0;
}
int safesend(int SendSock,char *SendBuffer,int SendBytesCount,int SendFlag)
{
int BytesSent = send(SendSock,SendBuffer,S
if(BytesSent == -1)
{
perror("send()");
return -1;
}
else if(BytesSent < SendBytesCount)
{
int RemainingBytes = SendBytesCount - BytesSent;
int temp = 0;
while(RemainingBytes)
{
temp = send(SendSock,SendBuffer+B
if(temp == -1)
{
perror("send()");
return -1;
}
BytesSent += temp;
RemainingBytes -= temp;
}
}
return BytesSent;
}
//whenever a client tries to connect, this function will be called
//this function
int ConnectNewClient(OnlineUse
{
//a sockaddr_in structure where information about a client requesting to get online
struct sockaddr_in TempSockAddr;
bzero(&TempSockAddr,sizeof
int sockaddrlen = sizeof(TempSockAddr);
int TempSock; //socket number allocated to the new client will be temporarily stored here
if((TempSock = accept(ListenerSock,(struc
{
perror("accept()");
return (-1);
}
else
{
if(TempSock > *MaxSock) *MaxSock=TempSock;
FD_SET(TempSock,MasterFDSe
printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd
printf("\nMaxSock = %d",*MaxSock);
return (TempSock);
}
}
As you can see...in function ConnectNewClient(),
the line printf("\nNew connection accepted from %s on socket %d\n",inet_ntoa(TempSockAd
is getting executed..but not the printf() following it?! why so?
Please help!
Regards,
logicTRANCE
I can also confirm that it works. What Alf666 means with "not strictly ANSI C" is that you declare your loop variables in the for loop. This is valid C++ (and C99), but is not ANSI C.
I've seen stuff like this happen before (one printf gets executed, but one just a few lines down will not work). This is usually due to a memory error. And, the problem is very likely not in the code that you provided. Do what Alf666 suggested, and run your program in the debugger.
I've seen stuff like this happen before (one printf gets executed, but one just a few lines down will not work). This is usually due to a memory error. And, the problem is very likely not in the code that you provided. Do what Alf666 suggested, and run your program in the debugger.
ASKER
i changed the pointer arguments to reference arguments (in call to ConnectNewClient()).
stil it wasnt working
then i used DDD, the graphical debugger that comes with Suse->KDE..it in turn used gdb..
it worked fine in DDD..and now it works fine in normal mode too (without the debuger!)
god knows what happened!
;-)
Happy Programming!
stil it wasnt working
then i used DDD, the graphical debugger that comes with Suse->KDE..it in turn used gdb..
it worked fine in DDD..and now it works fine in normal mode too (without the debuger!)
god knows what happened!
;-)
Happy Programming!
The version that you compiled with the -g switch works when you run it outside the debugger, is this also true for an optimized version?
It's possible that you are facing a compiler bug, but it's more likely that you still have a bug somewhere in your code that corrupts memory or the stack. If it now also works without the -g switch (you also could try compiling with -O), it's possible that you had an old object file somewhere that got linked in instead of an updated one. Usually make is pretty good with getting the dependencies right (I do however encounter this a lot under Windows), but it's not totally impossible.
It's possible that you are facing a compiler bug, but it's more likely that you still have a bug somewhere in your code that corrupts memory or the stack. If it now also works without the -g switch (you also could try compiling with -O), it's possible that you had an old object file somewhere that got linked in instead of an updated one. Usually make is pretty good with getting the dependencies right (I do however encounter this a lot under Windows), but it's not totally impossible.
ASKER
Er...actually i'm a linux newbie, and dunno much about using debuggers and compiler optimizations...and frankly, i dint understand what you actually meant by:
"The version that you compiled with the -g switch works when you run it outside the debugger, is this also true for an optimized version?"
are talking about the compiler version??
i'll lookup the manpagefor -g and -O options...but any help from youwill be really good as i want to understand the working of linux properly...and manpages are surely not enough!
before using anjuta, i was writing programme in kwrite and compile with g++ -o at Konsole...now in anjuta, i just have to press F9 and it compiles, but it give a bit different command:
g++ -Wall -g -c "XChatServer.cpp" -o "XChatServer.o"
At konsole, i used only
g++ -o XChatServer XChatServer.cpp
but the catch is even after compiling in anjuta, it was giving that error (segmentation fault)..and after once running it trhu the debugger, it stopped giving error...i'm puzzled...i did not make any changes at all to the programme, and still it works fine!
"The version that you compiled with the -g switch works when you run it outside the debugger, is this also true for an optimized version?"
are talking about the compiler version??
i'll lookup the manpagefor -g and -O options...but any help from youwill be really good as i want to understand the working of linux properly...and manpages are surely not enough!
before using anjuta, i was writing programme in kwrite and compile with g++ -o at Konsole...now in anjuta, i just have to press F9 and it compiles, but it give a bit different command:
g++ -Wall -g -c "XChatServer.cpp" -o "XChatServer.o"
At konsole, i used only
g++ -o XChatServer XChatServer.cpp
but the catch is even after compiling in anjuta, it was giving that error (segmentation fault)..and after once running it trhu the debugger, it stopped giving error...i'm puzzled...i did not make any changes at all to the programme, and still it works fine!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
g++ -o XChatServer XChatServer.cpp
g++ -g -o XChatServer XChatServer.cpp
g++ -O3 -o XChatServer XChatServer.cpp
all these compiled properly, though with some warnings (i've added a lot of code to th earlier one, thats why)
these are the warnings:
kapil@linux:~/ProjectStuff > g++ -O3 -o XChatServer XChatServer.cpp
XChatServer.cpp: In member function `void OnlineUser::SetClientDetai ls(char*,
sockaddr_in*, int, int, int)':
XChatServer.cpp:57: warning: NULL used in arithmetic
XChatServer.cpp:58: warning: NULL used in arithmetic
XChatServer.cpp:59: warning: NULL used in arithmetic
XChatServer.cpp: In member function `void
OnlineUser::UpdateClientDe tails(char *, sockaddr_in*, int, int, int)':
XChatServer.cpp:91: warning: NULL used in arithmetic
XChatServer.cpp:93: warning: NULL used in arithmetic
XChatServer.cpp:95: warning: NULL used in arithmetic
XChatServer.cpp: In function `int main()':
XChatServer.cpp:467: warning: passing NULL used for non-pointer argument 3 of `
void OnlineUser::UpdateClientDe tails(char *, sockaddr_in*, int, int, int)'
XChatServer.cpp: In function `int ConnectNewClient(OnlineUse rsList&, int, int&,
fd_set&)':
XChatServer.cpp:583: warning: passing NULL used for non-pointer argument 4 of `
int OnlineUsersList::AddClient (char*, sockaddr_in, int, int, int)'
XChatServer.cpp: In function `int HandleCtrlMessage(OnlineUs ersList*,
OnlineUser*)':
XChatServer.cpp:614: warning: passing NULL used for non-pointer argument 3 of `
void OnlineUser::SetClientDetai ls(char*, sockaddr_in*, int, int, int)'
XChatServer.cpp:614: warning: passing NULL used for non-pointer argument 4 of `
void OnlineUser::SetClientDetai ls(char*, sockaddr_in*, int, int, int)'
But the server code compiled.. and runs without crashing...since i hvent developed the client yet...i cannot test it properly...but i telneted it and the connection was made properly...
so far so good!!
but i might have to deal with these warnings..they are at some critical points in the programmes..i'll post a qn. related to that if the server doesnt work when proper clients are made...
i really need to get the stuff about NULLs clear!!
I'll get back in a day or two..gotta develop the client in QT.
Thanks and Regards,
Kapil
Happy Programming!
g++ -g -o XChatServer XChatServer.cpp
g++ -O3 -o XChatServer XChatServer.cpp
all these compiled properly, though with some warnings (i've added a lot of code to th earlier one, thats why)
these are the warnings:
kapil@linux:~/ProjectStuff
XChatServer.cpp: In member function `void OnlineUser::SetClientDetai
sockaddr_in*, int, int, int)':
XChatServer.cpp:57: warning: NULL used in arithmetic
XChatServer.cpp:58: warning: NULL used in arithmetic
XChatServer.cpp:59: warning: NULL used in arithmetic
XChatServer.cpp: In member function `void
OnlineUser::UpdateClientDe
XChatServer.cpp:91: warning: NULL used in arithmetic
XChatServer.cpp:93: warning: NULL used in arithmetic
XChatServer.cpp:95: warning: NULL used in arithmetic
XChatServer.cpp: In function `int main()':
XChatServer.cpp:467: warning: passing NULL used for non-pointer argument 3 of `
void OnlineUser::UpdateClientDe
XChatServer.cpp: In function `int ConnectNewClient(OnlineUse
fd_set&)':
XChatServer.cpp:583: warning: passing NULL used for non-pointer argument 4 of `
int OnlineUsersList::AddClient
XChatServer.cpp: In function `int HandleCtrlMessage(OnlineUs
OnlineUser*)':
XChatServer.cpp:614: warning: passing NULL used for non-pointer argument 3 of `
void OnlineUser::SetClientDetai
XChatServer.cpp:614: warning: passing NULL used for non-pointer argument 4 of `
void OnlineUser::SetClientDetai
But the server code compiled.. and runs without crashing...since i hvent developed the client yet...i cannot test it properly...but i telneted it and the connection was made properly...
so far so good!!
but i might have to deal with these warnings..they are at some critical points in the programmes..i'll post a qn. related to that if the server doesnt work when proper clients are made...
i really need to get the stuff about NULLs clear!!
I'll get back in a day or two..gotta develop the client in QT.
Thanks and Regards,
Kapil
Happy Programming!
It took me a few minutes to modify your code so that I could compile it, and it works fine on my system.
What I suggest is the following :
1) Compile with the "-g" option.
2) Execute under gdb :
gdb myprog
r
and, when it segfaults :
where
quit
And post the result.