2017-03-29 6 views
1

Lorsque j'utilise my_handler comme fonction, il n'y a pas d'erreur mais je ne peux pas parce que je dois utiliser une autre méthode.Erreur de gestion des signaux

Si je construis le code ci-dessous: erreur: utilisation non valide de membre functi sur (avez-vous oublié le '()'?)

Ceci est mon premier programme en C++

void Client::my_handler(int s){ 
    if (s == SIGINT){ 
     printf("SIGINT\n"); 
    // here I have to use stop_thread method 
    } 
} 


int main (int argc, const char **argv) { 
    Client client(argc, argv); 
    client.before_start(); 

    struct sigaction sigIntHandler; 

    sigIntHandler.sa_handler = (__sighandler_t) client.my_handler; //error here 
    sigemptyset(&sigIntHandler.sa_mask); 
    sigIntHandler.sa_flags = 0; 
    sigaction(SIGINT, &sigIntHandler, NULL); 

    client.run(); 

    return 0; 
} 
+0

Faites également attention à ce que vous essayez de faire dans un gestionnaire de signal. Les options sont assez limitées. J'ai peur de ne pas regarder à la main ce que vous pouvez utiliser en toute sécurité. – user4581301

Répondre

4

En C++, une fonction membre (une fonction associée à une instance de classe, telle que client.my_handler ici) n'est pas identique à une fonction régulière (quelque chose comme int main(int arg, const char** argv) ici). C'est pourquoi vous ne pouvez pas diffuser client.my_handler en __sighandler_t.

Client::my_handler a un paramètre caché, un Client*. Donc, vraiment, sa signature (d'une certaine perspective) ressemble à void my_handler(Client* this, int s). C++ fait quelques trucs en coulisses afin que vous puissiez référencer les variables de this sans avoir à faire this-> (la plupart du temps). Et quand vous faites quelque chose comme appel

client.my_handler(SIGINT) 

C++ est traduit que pour

my_handler(&client, SIGINT) 

Peut-être que maintenant vous pouvez voir la question: __sighandler_t est un alias pour un pointeur de fonction, mais client.my_handler est vraiment deux pointeurs: le pointeur de fonction pour my_handler et le pointeur sur client. Un gestionnaire de signal accepte uniquement un pointeur de fonction, pas un objet de fonction plus général (qui est un pointeur de fonction plus quelques autres données). La gestion du signal provient de C, mais les objets de fonction proviennent de C++.

La seule solution pour un gestionnaire de signal est une sorte de variable globale.

0

@SJL a fourni une excellente explication des raisons pour lesquelles cela ne fonctionne pas, et offre une solution de contournement de style C. Si vous pouvez utiliser Boost, boost::asio::signal_set peut être utilisé pour gérer les signaux dans un style plus C++. Le async_wait function peut recevoir un lambda, pointeur de fonction membre lié, ou tout autre type appelable avec la signature appropriée.

+0

Merci pour le type mais je ne peux pas l'utiliser – Bando