nodes: 0, module; 1, function_definition; 2, function_name:_CheckStatusAnalysisProcess; 3, parameters; 4, block; 5, identifier:self; 6, identifier:pid; 7, expression_statement; 8, comment:# TODO: Refactor this method, simplify and separate concerns (monitoring; 9, comment:# vs management).; 10, expression_statement; 11, if_statement; 12, expression_statement; 13, if_statement; 14, comment:"""Checks the status of an analysis process.
  
      Args:
        pid (int): process ID (PID) of a registered analysis process.
  
      Raises:
        KeyError: if the process is not registered with the engine.
      """; 15, call; 16, comparison_operator:pid in self._completed_analysis_processes; 17, block; 18, else_clause; 19, call; 20, comparison_operator:status_indicator in definitions.ERROR_STATUS_INDICATORS; 21, block; 22, attribute; 23, argument_list; 24, identifier:pid; 25, attribute; 26, expression_statement; 27, expression_statement; 28, expression_statement; 29, block; 30, attribute; 31, argument_list; 32, identifier:status_indicator; 33, attribute; 34, expression_statement; 35, expression_statement; 36, identifier:self; 37, identifier:_RaiseIfNotRegistered; 38, identifier:pid; 39, identifier:self; 40, identifier:_completed_analysis_processes; 41, assignment; 42, assignment; 43, assignment; 44, expression_statement; 45, expression_statement; 46, if_statement; 47, expression_statement; 48, expression_statement; 49, if_statement; 50, if_statement; 51, identifier:self; 52, identifier:_UpdateProcessingStatus; 53, identifier:pid; 54, identifier:process_status; 55, identifier:used_memory; 56, identifier:definitions; 57, identifier:ERROR_STATUS_INDICATORS; 58, call; 59, call; 60, identifier:status_indicator; 61, attribute; 62, identifier:process_status; 63, dictionary; 64, identifier:used_memory; 65, integer:0; 66, assignment; 67, assignment; 68, comparison_operator:process_status is None; 69, block; 70, else_clause; 71, assignment; 72, assignment; 73, boolean_operator; 74, block; 75, call; 76, block; 77, else_clause; 78, attribute; 79, argument_list; 80, attribute; 81, argument_list; 82, identifier:definitions; 83, identifier:STATUS_INDICATOR_COMPLETED; 84, pair; 85, identifier:process; 86, subscript; 87, identifier:process_status; 88, call; 89, identifier:process_status; 90, None; 91, expression_statement; 92, block; 93, identifier:process_information; 94, subscript; 95, identifier:used_memory; 96, boolean_operator; 97, attribute; 98, comparison_operator:used_memory > self._worker_memory_limit; 99, expression_statement; 100, expression_statement; 101, identifier:isinstance; 102, argument_list; 103, expression_statement; 104, expression_statement; 105, if_statement; 106, block; 107, identifier:logger; 108, identifier:error; 109, call; 110, identifier:self; 111, identifier:_TerminateProcessByPid; 112, identifier:pid; 113, string; 114, identifier:status_indicator; 115, attribute; 116, identifier:pid; 117, attribute; 118, argument_list; 119, assignment; 120, expression_statement; 121, attribute; 122, identifier:pid; 123, call; 124, integer:0; 125, identifier:self; 126, identifier:_worker_memory_limit; 127, identifier:used_memory; 128, attribute; 129, call; 130, call; 131, identifier:process_status; 132, identifier:dict; 133, assignment; 134, assignment; 135, comparison_operator:status_indicator == definitions.STATUS_INDICATOR_COMPLETED; 136, block; 137, expression_statement; 138, expression_statement; 139, if_statement; 140, if_statement; 141, expression_statement; 142, attribute; 143, argument_list; 144, string_content:processing_status; 145, identifier:self; 146, identifier:_processes_per_pid; 147, identifier:self; 148, identifier:_QueryProcessStatus; 149, identifier:process; 150, identifier:process_is_alive; 151, False; 152, assignment; 153, identifier:self; 154, identifier:_process_information_per_pid; 155, attribute; 156, argument_list; 157, identifier:self; 158, identifier:_worker_memory_limit; 159, attribute; 160, argument_list; 161, attribute; 162, argument_list; 163, subscript; 164, integer:0; 165, identifier:status_indicator; 166, call; 167, identifier:status_indicator; 168, attribute; 169, expression_statement; 170, assignment; 171, assignment; 172, comparison_operator:rpc_errors > self._MAXIMUM_RPC_ERRORS; 173, block; 174, identifier:process_is_alive; 175, block; 176, else_clause; 177, assignment; 178, parenthesized_expression; 179, identifier:format; 180, attribute; 181, identifier:pid; 182, identifier:status_indicator; 183, identifier:process_is_alive; 184, True; 185, identifier:process_information; 186, identifier:GetUsedMemory; 187, identifier:logger; 188, identifier:warning; 189, call; 190, identifier:self; 191, identifier:_KillProcess; 192, identifier:pid; 193, attribute; 194, identifier:pid; 195, attribute; 196, argument_list; 197, identifier:definitions; 198, identifier:STATUS_INDICATOR_COMPLETED; 199, call; 200, identifier:rpc_errors; 201, binary_operator:self._rpc_errors_per_pid.get(pid, 0) + 1; 202, subscript; 203, identifier:rpc_errors; 204, identifier:rpc_errors; 205, attribute; 206, expression_statement; 207, expression_statement; 208, expression_statement; 209, expression_statement; 210, expression_statement; 211, block; 212, identifier:process_status; 213, dictionary; 214, concatenated_string; 215, identifier:process; 216, identifier:name; 217, attribute; 218, argument_list; 219, identifier:self; 220, identifier:_rpc_errors_per_pid; 221, identifier:process_status; 222, identifier:get; 223, string; 224, None; 225, attribute; 226, argument_list; 227, call; 228, integer:1; 229, attribute; 230, identifier:pid; 231, identifier:self; 232, identifier:_MAXIMUM_RPC_ERRORS; 233, assignment; 234, assignment; 235, call; 236, assignment; 237, assignment; 238, expression_statement; 239, expression_statement; 240, pair; 241, string; 242, string; 243, parenthesized_expression; 244, identifier:format; 245, attribute; 246, identifier:pid; 247, attribute; 248, string_content:processing_status; 249, attribute; 250, identifier:add; 251, identifier:pid; 252, attribute; 253, argument_list; 254, identifier:self; 255, identifier:_rpc_errors_per_pid; 256, identifier:process_is_alive; 257, False; 258, identifier:rpc_port; 259, attribute; 260, attribute; 261, argument_list; 262, identifier:processing_status_string; 263, string; 264, identifier:status_indicator; 265, attribute; 266, assignment; 267, assignment; 268, string; 269, identifier:processing_status_string; 270, string_content:Process {0:s} (PID: {1:d}) is not functioning correctly.; 271, string_content:Status code: {2!s}.; 272, concatenated_string; 273, identifier:process; 274, identifier:name; 275, identifier:self; 276, identifier:_worker_memory_limit; 277, identifier:self; 278, identifier:_completed_analysis_processes; 279, attribute; 280, identifier:get; 281, identifier:pid; 282, integer:0; 283, attribute; 284, identifier:value; 285, identifier:logger; 286, identifier:warning; 287, call; 288, string_content:RPC error; 289, identifier:definitions; 290, identifier:STATUS_INDICATOR_RUNNING; 291, identifier:processing_status_string; 292, string; 293, identifier:status_indicator; 294, attribute; 295, string_content:processing_status; 296, string; 297, string; 298, identifier:self; 299, identifier:_rpc_errors_per_pid; 300, identifier:process; 301, identifier:rpc_port; 302, attribute; 303, argument_list; 304, string_content:killed; 305, identifier:definitions; 306, identifier:STATUS_INDICATOR_KILLED; 307, string_content:Process: {0:s} (PID: {1:d}) killed because it exceeded the; 308, string_content:memory limit: {2:d}.; 309, parenthesized_expression; 310, identifier:format; 311, attribute; 312, identifier:pid; 313, identifier:rpc_port; 314, concatenated_string; 315, identifier:process; 316, identifier:name; 317, string; 318, string; 319, string_content:Unable to retrieve process: {0:s} (PID: {1:d}) status via; 320, string_content:RPC socket: http://localhost:{2:d}
code: def _CheckStatusAnalysisProcess(self, pid):
      """Checks the status of an analysis process.
  
      Args:
        pid (int): process ID (PID) of a registered analysis process.
  
      Raises:
        KeyError: if the process is not registered with the engine.
      """
      # TODO: Refactor this method, simplify and separate concerns (monitoring
      # vs management).
      self._RaiseIfNotRegistered(pid)
  
      if pid in self._completed_analysis_processes:
        status_indicator = definitions.STATUS_INDICATOR_COMPLETED
        process_status = {
            'processing_status': status_indicator}
        used_memory = 0
  
      else:
        process = self._processes_per_pid[pid]
  
        process_status = self._QueryProcessStatus(process)
        if process_status is None:
          process_is_alive = False
        else:
          process_is_alive = True
  
        process_information = self._process_information_per_pid[pid]
        used_memory = process_information.GetUsedMemory() or 0
  
        if self._worker_memory_limit and used_memory > self._worker_memory_limit:
          logger.warning((
              'Process: {0:s} (PID: {1:d}) killed because it exceeded the '
              'memory limit: {2:d}.').format(
                  process.name, pid, self._worker_memory_limit))
          self._KillProcess(pid)
  
        if isinstance(process_status, dict):
          self._rpc_errors_per_pid[pid] = 0
          status_indicator = process_status.get('processing_status', None)
  
          if status_indicator == definitions.STATUS_INDICATOR_COMPLETED:
            self._completed_analysis_processes.add(pid)
  
        else:
          rpc_errors = self._rpc_errors_per_pid.get(pid, 0) + 1
          self._rpc_errors_per_pid[pid] = rpc_errors
  
          if rpc_errors > self._MAXIMUM_RPC_ERRORS:
            process_is_alive = False
  
          if process_is_alive:
            rpc_port = process.rpc_port.value
            logger.warning((
                'Unable to retrieve process: {0:s} (PID: {1:d}) status via '
                'RPC socket: http://localhost:{2:d}').format(
                    process.name, pid, rpc_port))
  
            processing_status_string = 'RPC error'
            status_indicator = definitions.STATUS_INDICATOR_RUNNING
          else:
            processing_status_string = 'killed'
            status_indicator = definitions.STATUS_INDICATOR_KILLED
  
          process_status = {
              'processing_status': processing_status_string}
  
      self._UpdateProcessingStatus(pid, process_status, used_memory)
  
      if status_indicator in definitions.ERROR_STATUS_INDICATORS:
        logger.error((
            'Process {0:s} (PID: {1:d}) is not functioning correctly. '
            'Status code: {2!s}.').format(
                process.name, pid, status_indicator))
  
        self._TerminateProcessByPid(pid)