Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Segfault TcpSocket.receive (mac)  (Lu 2354 fois)

0 Membres et 1 Invité sur ce sujet

roket

  • Newbie
  • *
  • Messages: 25
    • Voir le profil
Segfault TcpSocket.receive (mac)
« le: Novembre 23, 2015, 06:03:22 pm »
Bonsoir !
Je rencontre un problème de segfault très étrange sous mac avec l méthode receive de TcpSocket.
Elle segfault :
char data[256];
size_t received;
m_socket.receive(data, 256, received)

lldb indique :

Process 1479 stopped
* thread #2: tid = 0x750c, 0x000000010010e974 libsfml-network.2.3.dylib`sf::Socket::getHandle() const + 4, stop reason = EXC_BAD_ACCESS (code=1, address=0xc)
    frame #0: 0x000000010010e974 libsfml-network.2.3.dylib`sf::Socket::getHandle() const + 4
libsfml-network.2.3.dylib`sf::Socket::getHandle:
->  0x10010e974 <+4>: movl   0xc(%rdi), %eax
    0x10010e977 <+7>: popq   %rbp
    0x10010e978 <+8>: retq  
    0x10010e979 <+9>: nopl   (%rax)

 


Le même code fonctionne bien sous linux.
Une idée ?
Merci beaucoup

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Messages: 4321
    • Voir le profil
    • E-mail
Re : Segfault TcpSocket.receive (mac)
« Réponse #1 le: Novembre 24, 2015, 11:39:36 am »
Tu as un SSCCE ?
SFML / OS X developer

roket

  • Newbie
  • *
  • Messages: 25
    • Voir le profil
Re : Segfault TcpSocket.receive (mac)
« Réponse #2 le: Novembre 24, 2015, 05:29:25 pm »
Yes! merci!

main.cpp
#include <string>
#include <vector>
#include <thread>
#include <iostream>
#include <atomic>
#include <map>
#include <array>
#include <utility>
#include <SFML/Network.hpp>


typedef struct NetPackage NetPackage;
struct NetPackage
{
        std::string message;
};

typedef struct Client Client;
struct Client
{
    bool                    status;
    std::string     ipAddress;
    unsigned int    port;
    unsigned int        id;
    sf::TcpSocket       *socket;
};

class Server
{
    public:
       
        Server(const std::string &p_ipAddress, const unsigned int &p_port);
        ~Server();

        void launch();
       
        void disconnectClient(const unsigned int &p_id, const bool &p_notErase = true);

        void send(const NetPackage &p_package, const unsigned int &p_clientId);
        void sendAll(const NetPackage &p_package);
               
        private:
        void connectClient();
        void disconnectClients();
        void listenClients(unsigned int p_id);
        void parseMessage(const unsigned int &p_id, const std::string &p_message);

                std::string                             m_ipAddress;
                unsigned int                            m_port;

        std::map<unsigned int, Client>          m_clients;
        sf::TcpListener                         m_listener;

        std::thread*                            m_connectThread;
        std::map<unsigned int, std::thread*>    m_listenClientsThreads;

        std::atomic<bool>                       m_waitForClients;
        std::atomic<bool>                       m_listen;    
       
        unsigned int                            m_lastId;
       
};


Server::Server(const std::string &p_ipAddress, const unsigned int &p_port)
{
    m_ipAddress = p_ipAddress;
    m_port      = p_port;
    m_lastId    = 0;
}

void Server::launch()
{    
    if (m_listener.listen(m_port) != sf::Socket::Done)
    {
        std::cout << "Can't bind the socket" << std::endl;
    }
    m_waitForClients = true;
    m_listen = true;
    m_connectThread = new std::thread(&Server::connectClient, this);
   
}

void Server::send(const NetPackage &p_package, const unsigned int &p_clientId)
{
    char* data;
    data = (char*)p_package.message.c_str();
    m_clients[p_clientId].socket->send(data, p_package.message.size());
}

void Server::sendAll(const NetPackage &p_package)
{        
    for (std::pair<unsigned int, Client> client : m_clients)
    {
        send(p_package, client.first);
    }
}

void Server::parseMessage(const unsigned int &p_id, const std::string &p_message)
{
    // Accpet the client
    if (m_clients[p_id].status == false)
    {
        NetPackage np;
        // Message has to be like : name#type
        // Get the type
        std::string tmpMessage = p_message.substr(p_message.find("#") + 1);
        unsigned int playerType = stoi(tmpMessage);
       
        np.message = "200";
        send(np, p_id);    
    }
}

void Server::listenClients(unsigned int p_id)
{
    sf::TcpSocket *client = m_clients[p_id].socket;
   
    char data[256];
    size_t received = 0;
    std::string message("");
    while(m_listen)
    {
        sf::Socket::Status status;
        if ((status = client->receive(data, 256, received)) != sf::Socket::Done)
        {
            if (m_clients.find(p_id) != m_clients.end())
            {
                if (sf::Socket::Disconnected == status)
                {
                    m_clients[p_id].status = false;
                    disconnectClient(p_id);              
                }
            }
            std::cout << "Can't receive from client with IP " + m_clients[p_id].ipAddress << std::endl;  
        }
        std::string strData = std::string(data);
        if (strData.substr(strData.size() - 3) == "100")
        {
            message += strData.substr(0, strData.size() - 3);
            parseMessage(p_id, message);
        }
        else if (received == 3 && strData == "201")
        {
            m_clients[p_id].status = false;
            disconnectClient(p_id);
            return;
        }
        else
            message += std::string(data);
    }
}

void Server::connectClient()
{
    NetPackage package;
    package.message = "202";
   
    while(m_waitForClients)
    {
        sf::TcpSocket* client = new sf::TcpSocket();
       
        if (m_listener.accept(*client) != sf::Socket::Done)
        {
            delete client;
        }
        else
        {
           
            sendAll(package);

            std::thread *m_listenClientsThread  = new std::thread(&Server::listenClients, this, m_lastId);
            m_listenClientsThreads[m_lastId] = m_listenClientsThread;

            Client clientStruct;
            clientStruct.status = false;
            clientStruct.ipAddress = client->getRemoteAddress().toString();
            clientStruct.port = client->getRemotePort();
            clientStruct.id = m_lastId;
            clientStruct.socket = client;
           
            m_clients[m_lastId] = clientStruct;
           
            package.message = "200";
            send(package, m_lastId);
            package.message = "202";
           
            m_lastId++;
           
        }
    }
}

void Server::disconnectClient(const unsigned int &p_id, const bool &p_erase /* = true */)
{
    if (m_clients[p_id].status)
    {
        NetPackage package;
        package.message = "201";
       
        send(package, p_id);
    }
   
    m_clients[p_id].socket->disconnect();    
    m_listenClientsThreads[p_id]->detach();
   
    delete m_listenClientsThreads[p_id];
    delete m_clients[p_id].socket;
   
    m_listenClientsThreads.erase(p_id);

    if (p_erase)
        m_clients.erase(p_id);
}


void Server::disconnectClients()
{
    for (std::pair<unsigned int, Client>  client : m_clients)
    {
        disconnectClient(client.first, false);
    }
    m_clients.clear();
}

Server::~Server()
{
    disconnectClients();  
   
    m_listen = false;        
    m_waitForClients = false;
   
    m_listener.close();
    m_connectThread->detach();  
   
    delete m_connectThread;
}


int main()
{
        std::string ip = "127.0.0.1";
        int port = 50009;

        Server *server;
        server = new Server(ip, port);
        server->launch();


        sf::TcpSocket   socket;
        socket.connect(ip, port);

        char data[256];
        size_t received;

        socket.receive(data, 256, received);

        delete server;


}
 


Ce code segfault (ligne socket.receive du main) sous mac yosemite..
merci d'avance!!!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Messages: 4321
    • Voir le profil
    • E-mail
Re : Segfault TcpSocket.receive (mac)
« Réponse #3 le: Novembre 24, 2015, 05:46:14 pm »
Chez moi ça crash sur `if ((status = client->receive(data, 256, received)) != sf::Socket::Done)` car client == 0. Donc pas un problème avec SFML elle-même mais avec ton code.

Bonne chance pour le debuggage.  ;)
SFML / OS X developer

roket

  • Newbie
  • *
  • Messages: 25
    • Voir le profil
Re : Segfault TcpSocket.receive (mac)
« Réponse #4 le: Novembre 24, 2015, 10:32:10 pm »
Merci!!!