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

API, COM et SDKs Delphi Discussion :

Destruction de socket, un thread reste actif


Sujet :

API, COM et SDKs Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Par défaut Destruction de socket, un thread reste actif
    bonjour,

    J'utilise la classe TClientSocket (dans System.Win.ScktComp) avec laquelle je suis confronté à un problème lorsque je détruit l'objet.

    Je créé le socket par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     ClientSocket1        := TClientSocket.Create(nil);
     ClientSocket1.OnError:= ClientSocket1Error;
     ClientSocket1.Host := '192.168.0.1';
     ClientSocket1.Port := 502;
     ClientSocket1.Active:=true;
    Je le détruit par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ClientSocket1.Close;
    ClientSocket1.free;
    Dans mon cas l'adresse IP n'existe pas et donc lorsque je détruit l'objet, le thread qui a été créé par l'API n'est pas détruit et alors une exception apparait quelques secondes après la destruction du socket :

    Exception 'first chance' à $00000000. Classe d'exception $C0000005 avec un message 'access violation at 0x00000000: read of address 0x00000000'. Processus MyAPP.exe (5452)


    Si quelqu'un a une idée pour détruire le thread du socket en même temps qu'on détruit le socket ??

    En revanche je n'ai pas de problème lorsque je quitte mon application.
    Merci
    Franck

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 083
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 083
    Par défaut
    Citation Envoyé par franckcl Voir le message
    une exception apparait quelques secondes après la destruction du socket
    une VA en 00000000, typique d'un objet nil
    Probablement le membre privé de type TClientWinSocket interne au TClientSocket qui a été libéré, quoi qu'en lisant le code de Destroy, il n'y a pas d'affectation à nil

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if Assigned(ClientSocket1) then
    begin
      ClientSocket1.OnError := nil;
      if ClientSocket1.Active then
        ClientSocket1.Close();
      ClientSocket1.Free();
    end;

    Citation Envoyé par franckcl Voir le message
    Si quelqu'un a une idée pour détruire le thread du socket en même temps qu'on détruit le socket ??
    ClientType est par défaut à ctNonBlocking, cela utilise des variantes asynchrones des API, j'ignore si l'on peut dire que cela crée un thread mais ce n'est pas effectivement éloigné en terme de comportement !

    En réalité, comme tu es en mode ctNonBlocking, à mon avis, tu dois attendre la notification par OnError ou OnConnect pour poursuivre !

    Peux-tu différer la destruction ?
    Par exemple, dans le OnError, utiliser un PostMessage personnalisé pour libérer l'objet (un peu comme le Release d'une TForm, version différée du Free)

    Le TServerSocket fonctionne ainsi avec son DeferFree\CM_DEFERFREE mais pas le TClientSocket

    Cette VA apparait-elle qu'en Notification (first chance) puis une seconde fois en vrai Exception ?
    Ce n'est peut-être qu'un signalement par le déboggueur !

    Pense que le TClientSocket est fourni pas compatibilité avec Delphi 6, normalement le composant c'est TTCPClient ou TIdTCPClient, l'unité ScktComp a été dépréciée en Delphi 7 (depuis semble que l'on ne sache plus vraiment si ils sont considérés comme bon ou pas, leurs absences de la Palette amène un fort doute )
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre expérimenté Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Par défaut
    toujours le même qui répond...merci ShaiLeTroll
    Je viens d'essayer ton code mais ça ne change rien, j'avais déjà essayé de mettre le OnError à nil.
    J'ai essayé en release et si je le lance depuis l'IDE alors j'ai ce même message puis si je lance l'exécutable directement depuis windows, alors l'application se fige complêtement. (obligé de tuer la tâche)

    Il doit bien y avoir un moyen pour tuer le thread qui a été lancé par l'API et qui tourne en fond !

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 931
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut
    Y a-t-il un TimeOut à respecter avant de détruire ? Mais il devrait déclencher un OnError, je suppose.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    Membre expérimenté Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Par défaut
    Oui, Il y a un TimeOut, la fonction OnError est appellée environ 20 secondes après l'affectation de ClientSocket1.Active:=true
    Le problème est que lorsqu'arrive ce callback, l'objet est détruit car je ne l'utilise plus. Je ne peux pas me permettre d'attendre ce temps avant de le détruire. Je souhaiterai stopper le thread ou mettre fin à la connexion avant ce temps. En plus, je ne sais pas si l'adresse IP en question est valide ou non. Si elle est valide, il n'y a pas de problème puisque OnError n'est pas appelée.
    Et je ne sais même pas si un thread est en cours, c'est d'autant plus gênant que je ne peux pas le gérer.

  6. #6
    Membre expérimenté Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Par défaut
    Un nouvel indice à mon problème.
    Ce que je n'ai pas dit c'est que l'activation du socket est appellé par un thread:

    ClientSocket1.Active:=true; // appellé par un thread

    Ce thread appelle cette fonction régulièrement tant que la connexion n'est pas active (par exemple, en attendant la mise sous tension du serveur).

    J'ai essayé d'appeler cette fonction par un timer et je n'ai pas de problème.

    Mais bien sur il me faut absolument le lancer via le thread donc problème !

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 083
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 083
    Par défaut
    Citation Envoyé par franckcl Voir le message
    Je ne peux pas me permettre d'attendre ce temps avant de le détruire.
    C'est une erreur !
    Si tu conserves ton code en ctNonBlocking, il te suffit d'encapsuler le TClientSocket dans un ton propre objet

    Cet objet contient un TThread et un pool de TClientSocket, c'est je suppose ton TMySocket mais j'ai l'impression que tu lances plusieurs TMySocket alors que c'est lui qui devrait te fournir cette souplesse de connexion !

    A voir ton code, tes objets semblent très imbriqués les uns dans les autres avec MyLog, MyScheduler, je préfère au possible utiliser des Events pour les notifications et des propriétés pour le paramétrage pour avoir un faible couplage !

    Lorsqu'une action utilisateur rend cet la connexion obsolète, tu ne le libère pas immédiatement, tu appelles juste un Close, tu attends l'event OnError, OnConnect ou OnDisconnect pour passer à l'étape suivante

    Au lieu de gérer un seul socket, tu gères un pool de socket
    Ainsi lors que relance une nouvelle connexion ton objet Close le Socket en cours et le laisse en vie le temps qu'il soit dans un état "propre", et crée un nouvel objet

    Tu confonds ce que l'on "affiche à l'utilisateur" et ce que l'on fait réellement !
    Tu peux faire croire ce que tu veux à ton utilisateur tout en étant rigoureux dans ton code

    Citation Envoyé par franckcl Voir le message
    Il faut qu'on puisse détruire le socket à tout moment. J'utilise une interface graphique, l'utilisateur peut glisser des sockets les configurer et les démarrer quand il veut avec toute la souplesse d'un port de com série. Les déconnexion doivent être gérées et la liaison rétabli automatiquement au plus vite.
    En utilisant des threads séparés, il ne devrait y avoir aucun problème !
    tu peux "déclarer un socket" comme obsolète, tu le laisse vivre sa vie, si lors du OnConnect ou du OnError, il est voit qu'il a été annulé, il se ferme tout seul et proprement !

    Pendant ce temps, tu peux lance un autre objet qui lui prendra la main !

    Ton code à mon avis laisse trainer de la merde dans les API Windows, avoir CallBack\Message des Api WSA qui provoque un OnError sur un objet libéré est vraiment le signe d'un gros problème, preuve que Windows gère encore des Handles qui ne devrait plus être là !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Automation Excel - Processus Xl reste actif
    Par cooldidi dans le forum VBA Access
    Réponses: 2
    Dernier message: 03/03/2008, 15h38
  2. Programmation réseau : socket et thread
    Par roms712 dans le forum POSIX
    Réponses: 12
    Dernier message: 12/01/2007, 17h27
  3. popup qui reste actif tout le temps
    Par pas30 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 11/01/2007, 08h41
  4. Sockets TCP/ Threads
    Par guillaume16 dans le forum C++
    Réponses: 3
    Dernier message: 27/07/2006, 23h45
  5. Sockets et threads...
    Par Kiff dans le forum Réseau/Web
    Réponses: 6
    Dernier message: 27/07/2004, 17h35

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