c++, member thread object causes crash on structure deletion when it’s running

I've got a player class that has a kick function where I need to wait for a bit and kick the player afterwards for reasons out of my control and I also need to not hold the function while I wait, so my problem is; When the thread is done waiting and kicks the player, the disconnect event is risen and the memory for the player gets immediately freed, that causes the apparently unfinished thread to consistently cause a crash in that moment.

class Player
{
    public:
        Player();
        void kick();
        void kick(const char*, int color);

    protected:

        std::thread delaydKick_;

    private:
};

void Player::kick(){
    sampgdk_Kick(playerid); //tells API to kick the player
}


void Player::kick(const char* m, int color){
    sendMessage(m, color); // sends message to the player using API
    delaydKick_ = std::thread([p = this](){
        std::this_thread::sleep_for(std::chrono::seconds(3));
        p->kick(); //calls the function from the player object defined above
    });
    sampgdk::logprintf("Kicked (%s); %s", playername, m); //sends log to the server using API
}

//gets called by API when player disconnects
//PlayerDisconnectEvent just contains a pointer to the player which is on the heap
bool VirtualServerManager::OnPlayerDisconnect(PlayerDisconnectEvent&& e){
        //if disconnect is not kick
        if(e.player != nullptr){
            if( ( e.reason  < 2 ) && ( e.player->loggedIn == true ) ){
                e.player->getRefresh();
                e.player->updatePlayTime();
                SQLHandler sqlh(&sqlc);
                PlayerPersistance::save(e.player, &sqlh);
            }
            players.del(e.player->playerid); //here the player gets deleted when the api rises the event
        }
        return true;
    }

deffinition of the function del:

    template <typename T>
    void List<T>::del(size_t index){
        if(index >= current_max_){
            throw "pointer out of range";
        }
        if(items_[index] != nullptr){
            delete items_[index]; // it just calls delete on the pointer which is on the heap
            items_[index] = nullptr;
            count_--;
        }

}

to be clarify, the memory on the heap for the player which contains a thread object gets deleted, therefore terminating the thread object (delaydKick_) which results in the following crash:

terminate called without an active exception

trying to join the thread on the player's destructor results in:

terminate called after throwing an instance of 'std::system_error' what(): Resource deadlock avoided

Detaching the thread after creating it solves the issue, but I'd like to know why are these errors happening especially when I join the thread on the Player class destructor. Also I'd like to know if there's a way of getting around this without detaching the thread from the player.



Read more here: https://stackoverflow.com/questions/64395214/c-member-thread-object-causes-crash-on-structure-deletion-when-its-running

Content Attribution

This content was originally published by Rafael López at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: