• Advertisement
Sign in to follow this  

[SDL_Net] Broken pipe

This topic is 3229 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Error message:
SDLNet_TCP_Send: Server sockets cannot send
[New Thread 0xb79306c0 (LWP 6505)]

Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0xb79306c0 (LWP 6505)]
0xb80bb430 in __kernel_vsyscall ()
(gdb) bt
#0  0xb80bb430 in __kernel_vsyscall ()
#1  0xb7d4fd21 in send () from /lib/tls/i686/cmov/libc.so.6
#2  0xb7f1e40e in SDLNet_TCP_Send () from /usr/lib/libSDL_net-1.2.so.0
#3  0x0804edf7 in player::sendMessageNow (this=0x8a3dd40) at src/player.cpp:160




What went wrong? When sending(or receiving) check the result and if it's less than received/sent(ie client disconnects or something) I close the socket and get rid of the client altogether. Yet it crashes? Why? Edit: Another issue. Why on earth do I keep getting messages if I join to server, disconnect and join again? When server notices disconnection it a) removes player from vector containing players in that zone(and who would be receiving messages) b) deletes whole character class c) with deleting removes socket from set, closes socket and free socket set. Same thing is done on client. Yet when I join server again I get tons of messages. WTF? What do I need to do to completely get rid of those messages? Specifically following is called:
void server::removePlayerFromGame(int playerId) {
  myIdHandler->returnId(playerId);
  removePlayerFromZone(playerList[playerId]->getSectorX(), playerList[playerId]->getSectorZ(), playerId);

  delete playerList[playerId];
  playerList[playerId]=NULL;
  playerList.erase(playerId);
}

playerList is map<int, player*>. The function called is:
void server::removePlayerFromZone(int playerId, int sectorX, int sectorZ) {
  int zoneId=sectorX+sectorZ*gameWorld->getWorldHeight();
  for (vector<player*>::iterator it=playerZones[zoneId].begin(); it!=playerZones[zoneId].end();it++) {
    if((*it)->getId()==playerId) {
      (*it)=NULL;
      playerZones[zoneId].erase(it);
      return;
    }
  }
}

[Edited by - tneva82 on April 22, 2009 7:28:00 AM]

Share this post


Link to post
Share on other sites
Advertisement
Your post is almost completely incomprehensible to anyone without mind reading powers.

You might want to start focusing on one problem at a time, and keep that single problem in a single thread.

Then you might want to describe what you're doing, what you would expect that to accomplish, and what it actually accomplishes.

Another thing that would be good for anyone to be able to answer your question (one at a time) is to describe what you have already tried to do to resolve the problem, how you expected that to resolve the problem, and what actually happened instead.

Then you probably should post the code around the call site that leads up to the bad behavior, rather than some unrelated code that might or might not even get invoked.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
Your post is almost completely incomprehensible to anyone without mind reading powers.


I hoped somebody had some idea about common reasons for broken pipe since I have no idea what causes that one. I thought I wouldn't have to worry about that if I check wether functions send/receive as much as I tell it but obviously not enough since that doesn't work. Therefore I have zero idea what the heck broken pipe even means. I thought it meant connection lost and to guard against that you need to check wether send/receive sent/received as much as you told it but seems not enough to stop program from crashing midway.

Quote:
Then you might want to describe what you're doing, what you would expect that to accomplish, and what it actually accomplishes.


In essence, open connection, send messages as long as client is online, log off, be able to return to same server and log again. Works fine except randomly on rejoining it crashes with broken pipe issue. The second issue I posted I thought was connected to this.

And as for resolving...Pretty hard to even try when you have zero idea what the heck broken pipe even means! That's the darn issue. I get:


SDLNet_TCP_Send: Server sockets cannot send
[New Thread 0xb79306c0 (LWP 6505)]

Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0xb79306c0 (LWP 6505)]
0xb80bb430 in __kernel_vsyscall ()
(gdb) bt
#0 0xb80bb430 in __kernel_vsyscall ()
#1 0xb7d4fd21 in send () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7f1e40e in SDLNet_TCP_Send () from /usr/lib/libSDL_net-1.2.so.0
#3 0x0804edf7 in player::sendMessageNow (this=0x8a3dd40) at src/player.cpp:160





but have no idea where I should even look. I thought SDLNet_TCP_Send gives you <amount sent if it encounters error which I could check and if so react to it(generally by closing socket and removing player since connection seems to have been lost) but obviously not enough. We aren't talking about function returning errors here. We are talking program-crashing issues so what the heck SIGPIPE, broken pipe means?

But maybe I was too optimistic thinking somebody here might have some idea about common reasons for those. Ah well. Back to trying to figure out from SDL_Net's less than extensive documentation :(

And here's as well trimmed down from unrelated code related to the issue as I can:

mainloop:


while(running) {
listen();

Uint32 now=SDL_GetTicks();
logicTimeDif=logicTimeDif+(now-lastRound);
int logicSteps=ceil(logicTimeDif/SERVER_LOGIC_RUN_DIFFERENCE);

mainAction(logicSteps);

if(logicSteps>0) {
replyToClients();
}

lastRound=now;
logicTimeDif=logicTimeDif-logicSteps*SERVER_LOGIC_RUN_DIFFERENCE;
}
[/souce]

Listen loop:


int server::listen() {
char *buf;
vector<char*> messages;

TCPsocket newSocket=SDLNet_TCP_Accept(readSocket);

if(newSocket!=NULL) {
if(clientsConnected<MAX_CONNECTIONS) {
printf("Connection established!\n");
clientsConnected++;
int newPlayerId=myIdHandler->getNextId();
playerList.insert(pair<int, player*>(newPlayerId, new player() ));
playerList[newPlayerId]->addSocket(newSocket);
playerList[newPlayerId]->setId(newPlayerId);
} else {
// too many connections. Notify wannabe client and remove client from server
}
}

for (map<int, player*>::iterator it=playerList.begin();it!=playerList.end();it++) {
buf=new char[MAX_PACKET_SIZE];
char *temp;
int result=(*it).second->readNetwork();

if(result>0) { //huzah. We got something from network
//deal with message
} else if(result<0) {
removePlayerFromGame((*it).first);
}
if(buf!=NULL) delete[]buf;

}

return 0;
}



Then the read loop:



int server::replyToClients() {
if(playerList.size()>0) {
for (map<int, player*>::iterator it=playerList.begin();it!=playerList.end();it++) {
if((*it).second!=NULL) {
if((*it).second->sendMessageNow()<0) {
removePlayerFromGame((*it).first);
}
}
}
}
}



sendMessageNow() function:


int player::sendMessageNow() {
int numsent=0;

if(nextMessage!=NULL) {
if(strcmp(nextMessage, "")!=0) {

numsent=SDLNet_TCP_Send(mySocket, nextMessage, strlen(nextMessage)+1);
if(numsent<strlen(nextMessage)+1) {
printf("SDLNet_TCP_Send: %s. Tried to send: %s\n", SDLNet_GetError(), nextMessage);
return -1;
}
delete[] nextMessage;
nextMessage=NULL;

return numsent;
}
}

}



And playerRemovalFunction:



void server::removePlayerFromGame(int playerId) {

myIdHandler->returnId(playerId);
removePlayerFromZone(playerId, playerList[playerId]->getSectorX(), playerList[playerId]->getSectorZ());

delete playerList[playerId];
playerList.erase(playerId);

}


And finally removePlayerFromZone:


void server::removePlayerFromZone(int playerId, int sectorX, int sectorZ) {
int zoneId=sectorX+sectorZ*gameWorld->getWorldWidth();
for (vector<player*>::iterator it=playerZones[zoneId].begin(); it!=playerZones[zoneId].end();it++) {
if((*it)->getId()==playerId) {
(*it)=NULL;
playerZones[zoneId].erase(it);
//notify rest of the players that this player was removed
break;
}
}
}



That should cover it. Though still leaves simple question: What causes SIGPIPE crash? I thought SDLNet_TCP_Send was supposed to handle attempt to send via socket which leads to disconnected client by other ways than crashing. Would make servers pretty unsafe if they have to magically guess when client has been disconnected...

[Edited by - tneva82 on April 23, 2009 1:46:44 AM]

Share this post


Link to post
Share on other sites
Quote:
What causes SIGPIPE crash?


Let me google that for you.

In general, are you even sure that your player removal function always gets called? When a client disconnects cleanly, recv() returns 0, not -1, when you try to read from the socket. It seems as if your code doesn't actually deal with that case? It's hard to tell, because you're using the SDL_NET library, which I know very little about.

Given that the code you write has the same structure as regular Berkeley sockets, what value are you getting from SDL_NET? You'd certainly find better help and documentation if you used straight sockets.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
In general, are you even sure that your player removal function always gets called?


Pretty sure. Afterall there's "destructor called" text printed out on console everytime I disconnect. Also printed out size of the master player list and sector's playerlist size on the sector player is(here I noticed slight mistake but shouldn't affect. Doesn't matter wether I multiply Z by height or width when both are 6 afterall. Would have caused effect if the sector wouldn't have been square though). 0 and 0 for both.

Also SDLNet documentation says about return value:

Return Value

Returns the number of bytes sent. If the number returned is less than len, an error occured, such as the client disconnecting.

Doesn't say anything about 0 being special case. Just that it sends number of bytes send. Therefore I assumed that if len matches with sent amount all is fine, if not then socket is now on disconnected on their side and time to close it up here as well.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement