Skip to main content

Le système d'exploitation OpenVOS fournit une interface de programmation d'application (API) de haut niveau qui, dans l'ensemble, facilite la programmation du système. Mais parfois, cela devient trop facile - parce qu'un simple appel de sous-programme à une routine s$... peut cacher beaucoup de complexité.

Il s'agit du premier d'une série de messages irréguliers destinés à attirer votre attention sur ces pièges afin que vous puissiez les éviter dans vos modèles de demande.

Les méfaits des messages de la 25e ligne

La possibilité d'écrire un message sur la 25e ligne (ou sur la ligne inférieure) d'un terminal permet à un utilisateur (ou à un programme en cours d'exécution) d'informer les autres utilisateurs de conditions inhabituelles. L'interface en ligne de commande est la commande send_message. La commande et les programmes utilisateurs invoquent finalement le sous-routine API s$send_message. Les arguments de cet appel fournissent le nom_utilisateur d'un récepteur, le nom_du_module cible où cet utilisateur peut être connecté, le texte de notification et quelques indicateurs pour modifier certains aspects de l'opération. Les appelants privilégiés sont autorisés à spécifier le nom de l'expéditeur ; sinon, le nom par défaut est le nom d'utilisateur du processus d'envoi.

Jusqu'à présent, cela semble simple. Comme l'opération nécessite l'accès au terminal appartenant à un autre utilisateur, le noyau envoie la requête sur une file d'attente du serveur pour le processus TheOverseer sur le module cible. Normalement, le processus d'envoi attend alors l'état de la livraison du message mais peut choisir de ne pas attendre cette réponse.

Le processus Overseer pour tout module garde la trace de tous les processus de connexion et du terminal utilisé par ces processus. Lorsqu'il reçoit une demande d'envoi de message, il recherche dans sa liste de processus et de périphériques, et pour chaque nom d'utilisateur de processus qui correspond à l'argument receiver_name, il attache un port au périphérique terminal du processus, ouvre le port, écrit le message sur la ligne de notification, ferme le port et le détache. Si plusieurs processus correspondent à l'argument receiver_name, ce cycle d'attachement/ouverture/écriture/fermeture/détachement est répété pour chacun d'entre eux.

D'accord - c'est un peu plus compliqué que ce dont nous avions parlé au début. En y regardant de plus près, nous constatons qu'un module donné du système peut héberger des processus de connexion dans lesquels le véritable terminal est un appareil d'un autre système/module qui a utilisé Open StrataLink (OSL) pour se connecter sur le réseau (avec la commande login -module). Or, l'opération apparemment simple de connexion/ouverture/écriture/fermeture/détachement sur ce terminal doit impliquer des processus OSL et des appels de procédure à distance sur le réseau vers le module distant, et est beaucoup plus coûteuse que la manipulation sur le module.

L'amplification des effets se produit lorsque le nom d'utilisateur du récepteur est spécifié comme un nom d'étoile qui peut correspondre à plusieurs ou à tous les utilisateurs connectés. Et il est encore amplifié si le module cible est également spécifié comme nom d'étoile. Le pire cas serait d'envoyer le message à l'utilisateur "*.*". (tous les utilisateurs, tous les groupes) sur le module "*" (tous les modules du système actuel).

Mise en œuvre

s$expand_module_starname(target_module) =>  module_list;

foreach module_name in module_list
   send_overseer_request(module_name, send_message_request_data)
   The message is sent via a server queue and OSL to TheOverseer process
   on that module.

   TheOverseer  process on each receiving module then does:
   foreach terminal_process in TheOverseer’s list of
      login processes and sub-processes;

      if (terminal_process user_name matches receiver star name)
         if (messages_queued_for_device < 5)
            queue it for the login device
         else
            reject the request (e$too_many_terminal_messages)
   Utilisez simultanément jusqu'à 10 ports à la fois pour envoyer toute file d'attente
        les messages aux terminaux ;
   Pour chaque message pour chaque terminal
      Attacher le port
      Port ouvert
      s$control(...WRITE_SYSTEM_MESSAGE...)
      Fermer le port
      Détacher le port

Ce traitement est effectué en mode "no_wait_mode" pour chaque terminal afin que
Les retards (tels que les demandes d'E/S sur le réseau) ne concernent que les
le traitement des messages pour ce terminal.   

Si un message ne peut pas être délivré en 300 secondes, il est supprimé.

Lorsqu'une application utilise ce mécanisme pour signaler des erreurs, et qu'un flot d'erreurs se produit, l'application peut facilement s'embourber dans le signalement, alternant entre l'attente du traitement d'autres messages et l'inondation des terminaux des utilisateurs avec des messages qui arrivent trop vite pour être compris.

Évitement

Maintenant que vous savez ce qui se passe dans les coulisses, je peux vous guider :

  • Créez soigneusement des noms d'étoiles pour les noms d'utilisateurs et de modules afin de vous assurer que vous n'atteignez que les utilisateurs qui doivent recevoir le message et aucun autre. Par exemple, John_Doe.* ou *.Operations ou John_Doe.SysAdmin.
  • Envisager la mise en place d'une liste d'utilisateurs non starname pour notifier et envoyer chaque notification séparément.
  • Placez le détail des messages d'erreur ailleurs (un journal d'erreurs, par exemple) et utilisez s$send_message pour signaler la présence d'erreurs uniquement.
  • Limiter la fréquence des notifications à un niveau raisonnable (peut-être pas plus d'une fois par minute).
  • Supprimez tout message qui est identique au dernier envoyé. Le nouveau message se superposerait au précédent.

Si vous avez d'autres suggestions, n'hésitez pas à poster vos commentaires pour que d'autres personnes puissent les consulter.

2024 Stratus Technologies.