IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

wxWidgets Discussion :

wxSocket : "wxYield called recursively"


Sujet :

wxWidgets

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2006
    Messages : 83
    Points : 59
    Points
    59
    Par défaut wxSocket : "wxYield called recursively"
    J'ai implémenté une application client/serveur en utilisant les classes wxTCPServer, wxTCPClient, et wxTCPConnection, en me basant sur l'exemple "ipc" de wxWidgets.

    Cependant j'ai un assert "wxYield called recursively" du côté du serveur.
    Cette erreur (d'après certains - je n'ai pas encore testé) apparaît également avec l'exemple de wxWidgets si on lance 2 clients faisant chacun une action déclenchant un évènement.

    J'ai fait quelques recherches : on me dit de créer un thread pour chaque connection. Mais je ne suis pas sûr de bien comprendre: J'ai une classe MyServer dérivant de wxTCPServer, une classe MyClient dérivant de wxTCPClient et une classe MyConnection dérivant de wxTCPConnection. Dois-je dériver ma classe MyConnection de wxThread aussi ? Ou dois-je créer une classe dérivant de wxThread et contenant un objet de la classe MyConnection ?
    De plus, est-ce qu'il faut faire la même chose pour la classe MyServer ? Car sinon, si j'ai bien compris mon problème, si 2 clients se connectent en même temps (déclenchement de 2 évènements en même temps) l'assert devrait apparaître..

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2006
    Messages : 83
    Points : 59
    Points
    59
    Par défaut
    Dans la classe wxSocketBase (classe utilisée par wxTCPConnection), la macro PROCESS_EVENTS() est défini comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #define PROCESS_EVENTS()       \
    {                                \
      if ( wxThread::IsMain() )          \
          wxYield();                      \
      else                                \
          wxThread::Yield();	       \
    }
    A chaque fois c'est wxYield() qui est appelé, or je pense qu'en utilisant les threads c'est la fonction wxThread::Yield() qui devrait être utilisée pour éviter le problème. Cependant ce n'est pas le cas, je ne comprends pas..

    J'ai l'impression que ça ne parle à personne. Personnellement, je n'ai plus d'idées pour résoudre ceci. J'ai même ajouter un mutex en static dans la classe wxSocketBase pour protéger la macro PROCESS_EVENTS, mais ça ne marche toujours pas.

    Toute idée est la bienvenue.
    Merci.

  3. #3
    Membre émérite
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Points : 2 568
    Points
    2 568
    Par défaut
    Le seul truc qui me vient à l'esprit (sans avoir touché à la partie sockets de wxwidgets)
    C'est d'utiliser "wxYieldIfNeeded" à la place de "wxYield"

    Pourquoi je pense à cela, c'est parce que cela évite justement les appels récursifs.
    Cela ne doit pas fixer le problème de fond, mais bon… à défaut d’autre chose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Like wxYield, but fails silently if the yield is recursive.
    WXDLLIMPEXP_BASE bool wxYieldIfNeeded();

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2006
    Messages : 83
    Points : 59
    Points
    59
    Par défaut
    Merci beaucoup de m'avoir répondu.

    J'ai donc remplacé "wxYield" par "wxYieldIfNeeded" ; et je n'ai plus le message. Mais, la fonction est appelée en boucle ; ce qui "bloque" le programme.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2006
    Messages : 83
    Points : 59
    Points
    59
    Par défaut
    En faite, dans la fonction "_Wait" de la classe "wxSocketBase", la macro PROCESS_EVENTS() est appelé dans une boucle while.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    while(!done)
    {
        ...
     
        PROCESS_EVENTS();
    }
    Je continue mes recherches pour essayer de comprendre plus en détail le fonctionnement.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2006
    Messages : 83
    Points : 59
    Points
    59
    Par défaut
    J'ai une amélioration en ajoutant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wxSocketBase::Initialize();
    dans la fonction "bool OnInit()" de "class WXDLLEXPORT wxTCPEventHandlerModule: public wxModule". (Cette classe se trouve dans le fichier sckipc.cpp de la lib wxwidgets)

    L'erreur "wxYield called recursively" apparait maintenant à un seul endroit:
    wxTCPEventHandler::Server_OnRequest(..) => msg = codeci->Read8();
    wxDataInputStream::Read8(..) => m_input->Read(&buf, 1);
    wxInputStream::Read(..) => read = OnSysRead(p, size);
    wxSocketInputStream::OnSysRead(..) =>size_t ret = m_i_socket->Read((char *)buffer, size).LastCount();
    wxSocketBase::Read(..) => m_lcount = _Read(buffer, nbytes);
    wxSocketBase::_Read(..) => if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
    wxSocketBase::WaitForRead(..) => return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
    wxSocketBase::_Wait(..) => PROCESS_EVENTS();
    wxYield() => return wxTheApp && wxTheApp->Yield();
    wxApp::Yield(..) ==> wxFAIL_MSG( wxT("wxYield called recursively" ) );

    Cela se produit lorsque deux clients se connectent en même temps..

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo