Pular para o conteúdo principal

O Sistema Operacional OpenVOS fornece uma Interface de Programação de Aplicação (API) de alto nível que, de modo geral, facilita a programação do sistema. Mas às vezes, torna-se muito fácil - porque uma simples chamada de sub-rotina para uma rotina s$... pode esconder muita complexidade.

Este é o primeiro de uma série irregular de postos a chamar sua atenção para tais armadilhas para que você possa evitá-las em seus projetos de aplicação.

Os males das mensagens da 25ª Linha

A capacidade de escrever uma mensagem para a 25ª linha (ou o que quer que seja o fundo) de um terminal permite que um usuário (ou um programa em execução) notifique outros usuários sobre condições incomuns. A interface da linha de comando é o comando send_message. O comando e os programas do usuário acabam invocando a subrotina s$send_message API. Argumentos a esta chamada fornecem o nome_de_utilizador de um receptor, o nome_do_módulo_alvo onde esse usuário pode estar logado, o texto de notificação e algumas bandeiras para modificar aspectos da operação. Chamadores privilegiados têm permissão para especificar o nome do remetente; caso contrário, o nome_de_usuário do processo de envio é o padrão.

Até agora, parece simples. Como a operação requer acesso ao terminal de propriedade de outro usuário, o kernel envia o pedido em uma fila de servidores para o processo TheOverseer no módulo alvo. Normalmente, o processo de envio espera então pelo status de entrega da mensagem, mas pode optar por não esperar por esta resposta.

TheOverseer processo para qualquer módulo mantém o controle de todos os processos de login e do dispositivo terminal usado por esses processos. Quando recebe uma solicitação para enviar uma mensagem, ele procura sua lista de processos e dispositivos, e para cada processo de nome_de_usuário que corresponda ao argumento nome_de_servidor, ele anexa uma porta ao dispositivo terminal do processo, abre a porta, escreve a mensagem na linha de notificação, fecha a porta, e desprende a porta. Se vários processos corresponderem ao argumento do nome_do_consecedor, este ciclo de anexar/abrir/escrever/fechar/apagar é repetido para cada um deles.

Certo - isto é um pouco mais complicado do que falamos pela primeira vez. Explorando melhor, descobrimos que qualquer módulo do sistema pode estar hospedando processos de login onde o terminal real é um dispositivo em outro sistema/módulo que usou o Open StrataLink (OSL) para fazer login em toda a rede (com o comando login -modulo). Agora, a operação aparentemente simples de anexar/abrir/escrever/fechar/apagar nesse terminal tem que envolver processos OSL e chamadas de procedimento remoto de rede para o módulo remoto, e é muito mais cara do que o manuseio no módulo.

A ampliação dos efeitos acontece quando o nome do usuário receptor é especificado como um nome estrela que pode corresponder a vários ou a todos os usuários do login. E é ainda ampliado se o módulo alvo também for especificado como um nome estelar. O pior caso seria enviar a mensagem ao usuário "*.*". (todos os usuários, todos os grupos) no módulo "*" (todos os módulos do sistema atual).

Implementação

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)
   Simultaneamente, utilize até 10 portos de cada vez para enviar qualquer fila
        mensagens para os terminais;
   Para cada mensagem para cada terminal
      Fixar porta
      Porta aberta
      s$control(...WRITE_SYSTEM_MESSAGE...)
      Fechar o porto
      Desprender o porto

Este processamento é feito em modo no_wait_mode para cada terminal de modo que
atrasos (como solicitações de E/S em toda a rede) afetam apenas os
processamento de mensagens para aquele terminal.   

Se alguma mensagem não puder ser entregue em 300 segundos, ela é enxaguada.

Quando uma aplicação usa este mecanismo para relatar erros e uma enchente de erros aparece, a aplicação pode facilmente ficar atolada em relatórios, alternando entre esperar que outras mensagens sejam processadas e inundar os terminais dos usuários com mensagens que chegam muito rápido para serem compreendidas.

Evitar

Agora que você sabe o que está acontecendo nos bastidores, a orientação que posso lhe dar é:

  • Cuidadosamente crie nomes de estrelas para nomes de usuários e nomes de módulos para garantir que você alcance apenas os usuários que devem receber a mensagem e nenhum outro. Por exemplo, John_Doe.* ou *.Operations ou John_Doe.SysAdmin.
  • Considere a implementação de uma lista de usuários sem nome para notificar e enviar cada notificação separadamente.
  • Coloque o detalhe das mensagens de erro em outro lugar (um log de erros, por exemplo) e use s$send_message para alertar apenas para a presença de erros.
  • Limitar a freqüência das notificações a algo razoável (talvez não mais do que uma vez por minuto).
  • Suprimir qualquer mensagem que seja a mesma que a última enviada. A nova mensagem apenas sobreporia a anterior.

Se você tiver qualquer outra sugestão, envie seus comentários para que outros os vejam.

© 2024 Stratus Technologies.