Dans une installation de contrôle/commande d'une machine, avec 3 appareils principaux :
- 1 PC windows XP, puis Seven depuis quelques semaines (appareil maître) et une application Windev 18
- 1 automate programmable (type SAIA PCD3) appelé ici automate qui communique avec une liaison Ethernet
- 1 microbalance à quartz (appelée ici STC) qui communique avec une liaison RS232
j'ai un problème qui semble aléatoire concernant l'exécution d'un thread.
L'automate est commandé et scruté par le PC (protocole propriétaire encapsulé dans un paquet IP et communication par socket : période de scrutation dans le cas de cet exemple : 0.8 seconde environ). On utilise le Thread_2_automate.
Le STC est commandé et scruté par le PC (liaison série RS232 9600 bauds, période dans cet exemple période 4 secondes environ). On utilise le Thread_3_STC.
Ce qui suit est un extrait d'un fichier historique, généré par l'application sur le PC
Tous les événements liés à la communication avec le STC sont mémorisés.
LE PROBLEME :
De temps à autre (intervalle de temps de quelques heures, quelques jours ou quelques semaines, mais en général quelques jours) la procédure lancée par le code suivant (situé dans une procédure du thread principal et exécutée périodiquement) ne démarre pas
On ne va pas dans la première ligne de Acquisition_Stc et cela paralyse l'application. On le sait parce que dans cette première ligne se trouve le code
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Si ThreadEtat("Thread_3_stc") = threadInexistant ALORS ThreadExécute("Thread_3_stc",threadNormal,Acquisition_Stc)
qui laisse une ligne dans l'historique quand elle est exécutée (exemple plus loin)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Histo(''Acquisition_stc : première ligne de la procédure'')
Plusieurs configurations matérielles ont été essayées.
Cela n'a aucune influence.
La routine Histo qui génère tous les messages est la seule pouvant être lancée simultanément par tous les threads. Elle est protégée par un mutex
Aucune action extérieure qui pourrait utiliser les mêmes ressources n'est utilisée (le problème peut survenir au milieu de la nuit, le week end, …)
Pour la compréhension du texte, des lignes on été insérées dans l'historique pour les commentaires
Deux lignes de code ont été insérées en exemple
Il y a de nombreux messages parce qu'un mode de contrôle a été activé.
La présence ou l’absence de ce mode de contrôle n'influe pas sur la présence ou l’absence de ce défaut.
La période de scrutation n'intervient pas non plus :si on va plus vite, c'est l'appareil distant (le STC commandé et contrôlé par la liaison série) qui ne remplit plus d'autres fonctions dont il a la charge - d'ailleurs sans le signaler (autre problème...)
EXTRAIT DE L'HISTORIQUE
Séquence normale :
.
lignes précédentes. Puis :
.
.
13/09/2013 ; 13:54:50 ; Ce message avait 6 caractère(s)
13/09/2013 ; 13:54:50 ; Th_acquisition_stc : Demande de vie restante E7 : réponse en numérique retenue 97 pour 30 nécessaires
13/09/2013 ; 13:54:50 ; Th_acquisition_stc : Quartz OK
On passe ici au compte rendu de la commande suivante (commande F5)
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : Commande envoyée : F5
13/09/2013 ; 13:54:50 ; Détail : 36 70 53 RC LF
13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse à la commande F5 : B1
13/09/2013 ; 13:54:50 ; Détail : 36 66 49 RC LF
13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
On passe ici au compte rendu de la commande suivante (commande F9)
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : Commande envoyée : F9
13/09/2013 ; 13:54:50 ; Détail : 36 70 57 RC LF
13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse à la commande F9 : B6
13/09/2013 ; 13:54:50 ; Détail : 36 66 54 RC LF
13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
Cette ligne est la dernière ligne, correcte, générée par Demande_dialogue_STC à la fin de la procédure qui se termine et libère le thread.
Suite de l'historique :
13/09/2013 ; 13:54:57 ; Lecture sur l'automate
13/09/2013 ; 13:54:57 ; Rafraîchissement synoptique
13/09/2013 ; 13:54:59 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
13/09/2013 ; 13:54:59 ; Lecture sur l'automate
13/09/2013 ; 13:54:59 ; Rafraîchissement synoptique
13/09/2013 ; 13:55:00 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
13/09/2013 ; 13:55:00 ; Lecture sur l'automate
13/09/2013 ; 13:55:00 ; Rafraîchissement synoptique
13/09/2013 ; 13:55:01 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
DEBUT DE LA SEQUENCE NUMERO N*: ACQUISITION_STC
ICI, FONCTIONNEMENT CORRECT
La première ligne de code génère la ligne d'historique suivante, la deuxième lance effectivement la procédure.
13/09/2013 ; 13:55:01 ; Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = -1
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Histo("Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = " + ThreadEtat("Thread_3_stc")) Si ThreadEtat("Thread_3_stc") = threadInexistant ALORS ThreadExécute("Thread_3_stc",threadNormal,Acquisition_Stc)
Les deux messages suivants sont normaux et viennent s'interposer ici (les différents threads sont asynchrones)*: le 1er est généré par le thread Thread_2_automate, le 2nd par le thread principal.
13/09/2013 ; 13:55:01 ; Lecture sur l'automate
13/09/2013 ; 13:55:01 ; Rafraîchissement synoptique
Contrôle : on est entré dans la procédure Acquisition_Stc. Cette ligne d'historique est générée dans la première ligne de la procédure Acquisition_Stc, qui appelle immédiatement la procédure Th_acquisition_stc
13/09/2013 ; 13:55:01 ; Acquisition_stc : première ligne de la procédure
Contrôle : on est entré dans la procédure Th_acquisition_stc. Cette ligne d'historique est générée dans la première ligne de la procédure, qui va gérer les dialogues par la liaison série.
13/09/2013 ; 13:55:01 ; Th_acquisition_stc : première ligne de la procédure
Tout est correct.
On passe ici au compte rendu de la première commande envoyée à l'appareil distant (le STC) (commande I89)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : I89
13/09/2013 ; 13:55:01 ; Détail : 36 73 56 57 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 6 caractère(s)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande I89 : B
13/09/2013 ; 13:55:01 ; Détail : 36 66 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 4 caractère(s)
On passe ici au compte rendu de la commande suivante (commande E1)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : E1
13/09/2013 ; 13:55:01 ; Détail : 36 69 49 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
On passe ici au compte rendu de la commande suivante (commande E7)
13/09/2013 ; 13:55:01 ; Th_acquisition_stc : Demande de vie restante E7 : réponse en numérique retenue 97 pour 30 nécessaires
13/09/2013 ; 13:55:01 ; Th_acquisition_stc : Quartz OK
On passe ici au compte rendu de la commande suivante (commande F5)
On a fait un cycle complet depuis le début de cet exemple
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : F5
13/09/2013 ; 13:55:01 ; Détail : 36 70 53 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande F5 : B1
13/09/2013 ; 13:55:01 ; Détail : 36 66 49 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
On passe ici au compte rendu de la commande suivante (commande F9)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : F9
13/09/2013 ; 13:55:01 ; Détail : 36 70 57 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande F9 : B6
13/09/2013 ; 13:55:01 ; Détail : 36 66 54 RC LF
13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
Le cycle se termine normalement. L'appareil distant (le STC) à répondu correctement et la séquence s'est terminée normalement.
On continue :
.
.
13/09/2013 ; 13:55:05 ; Lecture sur l'automate
13/09/2013 ; 13:55:05 ; Rafraîchissement synoptique
13/09/2013 ; 13:55:06 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
DEBUT DE LA SEQUENCE NUMERO N+1*: ACQUISITION_STC
ICI, FONCTIONNEMENT DEFECTUEUX.
13/09/2013 ; 13:55:06 ; Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = -1
13/09/2013 ; 13:55:06 ; Lecture sur l'automate
13/09/2013 ; 13:55:06 ; Rafraîchissement synoptique
et plus rien ne se passe : on n'entre pas dans la procédure Acquisition_Stc, si on fait la moindre action (souris par exemple), on a le sablier.
Le thread principal est bloqué
C'EST LE DEFAUT.
Après CTRL ALT SUP, on arrête l'application, on relance et tout redevient OK.
Pas d'erreur système, pas d'erreur de l'application (sauf quand on cherche à la relancer : le système signale alors que l'appli est plantée)
Redémarrage:
13/09/2013 ; 14:02:55 ; Démarrage du programme.
13/09/2013 ; 14:02:55 ; Répertoire programme : C:\Program Files (x86)\
13/09/2013 ; 14:02:55 ; Répertoire privé : C:\ProgramData\Apsy11\Prive_APSY-E760-PC\
13/09/2013 ; 14:02:55 ; Répertoire public réseau : C:\ProgramData\Apsy11\Data\
13/09/2013 ; 14:02:55 ; Répertoire documentation : C:\ProgramData\Apsy11\Textes\
13/09/2013 ; 14:02:55 ; Tentative d'ouverture de la liaison COM1
13/09/2013 ; 14:02:55 ; Ouverture OK : paramètres COM1 9600 1 8 0
13/09/2013 ; 14:02:55 ; Ouverture du port de communication 1 vers le STC OK.
13/09/2013 ; 14:02:55 ; Le nouvel utilisateur courant est Jean François LEBRUN
13/09/2013 ; 14:02:55 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
13/09/2013 ; 14:02:55 ; Lecture sur l'automate
.
.
.
etc.
Quelqu'un a-t-il une intuition, pour une voie de recherche ?
Le problème est-il suffisamment bien expliqué ?
Partager